3

I have a small utility I am working on that deletes old user profiles from domain machines.

Basically, where I am stuck is looking for a better process to delete remote directories.

I know I can use the System.IO and delete it from the UNC path, but I am not happy with the performance of the network deletion. It can take hours to delete medium sized profiles, and if there are dozens or hundreds of profile or machines this is not feasible as a solution.

So this appears to be out of the question

The best I can find appears to be PSExec calls, but I want something managed.

Are there any .NET classes that can invoke the remote machine to complete the deletion of the directory instead of relying on the calling machine?

Community
  • 1
  • 1
Austin T French
  • 5,022
  • 1
  • 22
  • 40
  • Related: http://stackoverflow.com/questions/9466799/file-delete-and-directory-delete-network-performance – Robert Harvey Aug 08 '13 at 03:53
  • @RobertHarvey thanks, thats exactly why I want to avoid the common Directory.Delete() method, and any other remote delete. I want to remotely invoke the remote machine to do the operations. Hopefully that makes sense. 200+ machines at a time and multiple profiles over 1GB really adds up! – Austin T French Aug 08 '13 at 03:57
  • Have you considered spawning a process to execute `rd /s` from within the cmd-shell? –  Aug 08 '13 at 06:29
  • *Why* do you want something managed? Why does this need to be a .NET class? – Cody Gray - on strike Aug 08 '13 at 08:27
  • @AndersUP if I can do it on the remote PC, yes that is what great – Austin T French Aug 08 '13 at 11:20
  • @CodyGray it does not have to be managed, but if I can integrate it into the solution somehow more fluidly than PsExec allows it would be great – Austin T French Aug 08 '13 at 11:21

2 Answers2

1

If your client computers don't detect this as a virus, you can use it to execute remote commands on your network computers, including folder deletions:

PsExec v1.98

Introduction

Utilities like Telnet and remote control programs like Symantec's PC Anywhere let you execute programs on remote systems, but they can be a pain to set up and require that you install client software on the remote systems that you wish to access. PsExec is a light-weight telnet-replacement that lets you execute processes on other systems, complete with full interactivity for console applications, without having to manually install client software. PsExec's most powerful uses include launching interactive command-prompts on remote systems and remote-enabling tools like IpConfig that otherwise do not have the ability to show information about remote systems.

I have no idea how it works. In .NET code the idea would be to send RPC calls to a remote application that you control, which is easy enough provided you already have said application running on the target computers. The mechanism used would be .NET Remoting or WCF.

Community
  • 1
  • 1
Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
  • Yes, I could but there are still some issues. (Also mentioned in my OP for PSExec) One is that PsExec would require an instance on the the PC that calls it for each deletion... Although Point 2 intrigues me. I assume I can push the executable to the machine, use remoting / WCF and perhaps a socket to report back to the "server" or calling machine all on the fly... Might be more involved than I hoped for, but the advantage may be worth it. – Austin T French Aug 08 '13 at 04:04
  • The PsExec page says it doesn't require a client program running on the target computer. – Robert Harvey Aug 08 '13 at 04:05
  • No, it doesn't but I am looking at writing something like PsExec into the .NET utility. PsExec also has a very funny EULA, we use it widely but I do not want to worry about it getting picked up wrong later and EULA violations – Austin T French Aug 08 '13 at 04:08
1

Inspired by this answer, I did some minor modifications. I can't get it to run 100% managed, as I get an error code 9 (The storage control block address is invalid) when I try to run the rd-command from within the code itself.

The base functionality is blindingly fast on my small test-setup, but given that you overrule the "Are you sure?" prompt, it is also fairly dangerous if you specify the wrong path, so wear your hard hat as you proceed:

If you execute echo Y | rd /S c:\Temp\test in any command shell, you'll remove C:\Temp\Test and anything below it very quickly and without warning.

But executing this solution directly in the code doesn't work. So my quick fix is to place a bat-file (called DeleteTest.bat) on the machine, containing only this line and then execute the bat file by WMI.

In my small test, it deletes ~900 files of a total of ~200 mb in a second or so.

Also, in addition to the answer cited I get the return code, so my full code becomes:

        var processToRun = new[] { "c:\\Temp\\DeleteTest.bat" };

        var connection = new ConnectionOptions();
        connection.Username = "me";
        connection.Password = "password";
        var wmiScope = new ManagementScope(String.Format("\\\\{0}\\root\\cimv2", "MyRemoteMachine"), connection);
        var wmiProcess = new ManagementClass(wmiScope, new ManagementPath("Win32_Process"), new ObjectGetOptions());
        var result = wmiProcess.InvokeMethod("Create", processToRun);
        Console.WriteLine(
        "Creation of process returned: " + result);

You will obviously also need the bat file to be generated (by code or pre-generated) and copied to the destination, but that should be trivial.

Community
  • 1
  • 1