Need help converting PowerShell to C# code

-1

So i have this powershell code:

try{
    $ComputerWMIObject = Get-WmiObject Win32_ComputerSystem -ComputerName "$oldComputerName" -Authentication 6
    if ( $ComputerWMIObject ){
        $result = $ComputerWMIObject.Rename("$newComputerName", $ADUserPassword , $ADUserName )
        switch($result.ReturnValue)
        {
            0 {
                if ( $Restart.IsChecked ) {
                    Get-WmiObject Win32_OperatingSystem -ComputerName "$oldComputerName" | ForEach-Object {$restart = $_.Win32Shutdown(6)}
                    $ResultText.Text = "Computer $oldComputerName was renamed to $newComputerName and restarted"
                } else {
                    $ResultText.Text = "Computer $oldComputerName was renamed to $newComputerName restart computer to finish"
                }

            }
            5 { $ResultText.Text = "Computer was not renamed. Please check if you have admin permissions (ReturnCode 5)" }
            default { $ResultText.Text = "ReturnCode $($result.ReturnValue)"}
        }
    }else{
        $ResultText.Text = "Couldn't create WMI Object on $oldComputerName"
    }
}catch{
    $ResultText.Text = $_
}

I'm trying to convert this to C# and can't find a way to do this. I just don't understand how to create WMI object.

It would be very helpful if you can post and example on how to do this. I've read this Remotely change computer name for a Windows Server 2008 machine using C#? topic. And it throws an exception may be its because of this line:

Authentication = AuthenticationLevel.PacketPrivacy

I'm using System.Net.Security namespace and as it's stated in comment PacketPrivacy exists only there.

Since I can't ask there because I have low rating I've asked again.

Would be grateful if any one can help me.

PS: I know this can be done using NETDOM but I would prefer using WMI object.

ADDED:

I'm trying to use this:

var remoteControlObject = new ManagementPath
{
    ClassName = "Win32_ComputerSystem",
    Server = oldName,
    Path = oldName + "\\root\\cimv2:Win32_ComputerSystem.Name='" + oldName + "'",
    NamespacePath = "\\\\" + oldName + "\\root\\cimv2"
};

var conn = new ConnectionOptions
{
    Authentication = AuthenticationLevel.PacketPrivacy,
    Username = accountWithPermissions.Domain + "\\" + accountWithPermissions.UserName,
    Password = accountWithPermissions.Password
};

var remoteScope = new ManagementScope(remoteControlObject, conn);

var remoteSystem = new ManagementObject(remoteScope, remoteControlObject, null);

ManagementBaseObject newRemoteSystemName = remoteSystem.GetMethodParameters("Rename");
var methodOptions = new InvokeMethodOptions();

newRemoteSystemName.SetPropertyValue("Name", newName);
newRemoteSystemName.SetPropertyValue("UserName", accountWithPermissions.UserName);
newRemoteSystemName.SetPropertyValue("Password", accountWithPermissions.Password);

ManagementBaseObject outParams = remoteSystem.InvokeMethod("Rename", newRemoteSystemName, null);

And I get this error Server RPC is unavailable. (Exception HRESULT: 0x800706BA) here:

ManagementBaseObject newRemoteSystemName = remoteSystem.GetMethodParameters("Rename");

ADDED2:

Ok, I guess I found out what causes an error.

i've changed original conn User name from

Username = oldName + "\\" + accountWithPermissions.UserName,

to

Username = accountWithPermissions.Domain + "\\" + accountWithPermissions.UserName,

and error happens, if I use old code I get ACCESS_IS_DENIED and that's correct because that user doesn't have rights.

So what's wrong if I use Domain\User may be I should change NamespacePath in remoteControlObject to be able to work with domain user authentication?

c#
powershell
asked on Stack Overflow Nov 24, 2014 by BolnoYGaD • edited May 23, 2017 by Community

1 Answer

0

I was unable to find a way resolve this issue and no one seems to have an answer.

So I've solved this by using NETDOM when Server RPC is unavailable. (Exception HRESULT: 0x800706BA) actually any error happens I will add access denied check so it won't try NETDOM when this happens;

var remoteControlObject = new ManagementPath
{
    ClassName = "Win32_ComputerSystem",
    Server = oldName,
    Path = oldName + "\\root\\cimv2:Win32_ComputerSystem.Name='" + oldName + "'",
    NamespacePath = "\\\\" + oldName + "\\root\\cimv2"
};

string domain = accountWithPermissions.Domain;
string user = accountWithPermissions.UserName;

var conn = new ConnectionOptions
{
    Authentication = AuthenticationLevel.PacketPrivacy,
    Username = domain + "\\" + accountWithPermissions.UserName,
    Password = accountWithPermissions.Password
};
var remoteScope = new ManagementScope(remoteControlObject, conn);

var remoteSystem = new ManagementObject(remoteScope, remoteControlObject, null);
try
{
    ManagementBaseObject newRemoteSystemName = remoteSystem.GetMethodParameters("Rename");
    newRemoteSystemName.SetPropertyValue("Name", newName);
    newRemoteSystemName.SetPropertyValue("UserName", accountWithPermissions.UserName);
    newRemoteSystemName.SetPropertyValue("Password", accountWithPermissions.Password);
    ManagementBaseObject outParams = remoteSystem.InvokeMethod("Rename", newRemoteSystemName, null);
}
catch (Exception e)
{
    this.Res.Inlines.Add(string.Format("Ошибка:\n" + e.Message + "\n"));
    this.Res.Inlines.Add(string.Format("Пробуем переименовать используя NETDOM\n"));
    bool restart = false;
    PowerNETDOM(oldName, newName, accountWithPermissions, restart);
}

Server RPC is unavailable. (Exception HRESULT: 0x800706BA) is happening not because my changes to the script. This error if fired only by few PC's as I found out it can happen in many cases more about this here: Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA) . And changing settings on a remote PC makes me go and check the settings directly from that PC. In that case I can just rename PC not even trying to find out what this happening. That's why I do use NETDOM because for some reason it doesn't have problems renaming that PC remotely.

    private static void PowerNETDOM(String oldName, String newName, NetworkCredential accountWithPermissions, bool restart)
    {
        using (PowerShell PowerShellInstance = PowerShell.Create())
        {
            PowerShellInstance.AddScript
                (
                    "param($Restart,$oldComputerName,$newComputerName,$ADUserPassword,$ADUserName);" +
                    "function ConvertTo-Encoding ([string]$From, [string]$To){" +
                    "   Begin{ $encFrom = [System.Text.Encoding]::GetEncoding($from);$encTo = [System.Text.Encoding]::GetEncoding($to); }" +
                    "   Process{ $bytes = $encTo.GetBytes($_);$bytes = [System.Text.Encoding]::Convert($encFrom, $encTo, $bytes);$encTo.GetString($bytes)}" +
                    "}" +
                    "$tmp = NETDOM RENAMECOMPUTER $oldComputerName /NewName:$newComputerName /ud:$ADUserName /pd:$ADUserPassword /Force $res_text | ConvertTo-Encoding \"cp866\" \"windows-1251\";" +
                    "$tmp > C:\\Temp\\rename.txt;$tmp;"
                );

            PowerShellInstance.AddParameter("restart", restart);
            PowerShellInstance.AddParameter("newComputerName", newName);
            PowerShellInstance.AddParameter("oldComputerName", oldName.ToString());
            PowerShellInstance.AddParameter("ADUserPassword", accountWithPermissions.Password);
            PowerShellInstance.AddParameter("ADUserName", accountWithPermissions.Domain + "\\" + accountWithPermissions.UserName);

            PowerShellInstance.Invoke();
        }

    }
answered on Stack Overflow Dec 3, 2014 by BolnoYGaD • edited May 23, 2017 by Community

User contributions licensed under CC BY-SA 3.0