Creating share programmatically fails with error 9 - c#

ObjectGetOptions options = new ObjectGetOptions();
ManagementPath p = new ManagementPath("\\\\server01\\root" + "\\cimv2:Win32_Share");
// Make a connection to a remote computer.
ManagementScope scope = new ManagementScope("\\\\server01\\root\\cimv2");
scope.Connect();
// Create a ManagementClass object
ManagementClass managementClass = new ManagementClass(scope, p, options);
// Create ManagementBaseObjects for in and out parameters
ManagementBaseObject inParams = managementClass.GetMethodParameters("Create");
ManagementBaseObject outParams;
// Set the input parameters
//inParams["Description"] = String.Empty;
inParams["Name"] = "test";
inParams["Path"] = #folderPath;
inParams["Type"] = 0x0; // Disk Drive
// Invoke the method on the ManagementClass object
outParams = managementClass.InvokeMethod("Create", inParams, null);
// Check to see if the method invocation was successful
if ((uint)(outParams.Properties["ReturnValue"].Value) != 0)
{
throw new Exception("Unable to share directory. Error code: " + outParams.Properties["ReturnValue"].Value);
}
}
catch (Exception e)
{
MessageBox.Show(e.Message.ToString());
}
}
I am using the following code to set up a share, but I am always getting a return value of 9 which means invalid name. I am passing a string and have tried to use an explicit string and I still get error 9.
I am creating the share remotely rather than on local machine however. I have tried to make sure I am connecting to the remote WMI provider, but I am not sure if I have been successful.
Any suggestions from WMI gurus and others is greatly appreciated.

Found the answer on another site. The folder path needs to be the local path to the machine the share is created on, not a UNC path like I was using.

I had the same error. In my case though the problem was a trailing backslash. Doing directoryPath.TrimEnd('\') solved the problem.

Return Values
Returns one of the values in the following table or any other value to indicate an error.
0 – Success
2 – Access denied
8 – Unknown failure
9 – Invalid name
10 – Invalid level
21 – Invalid parameter
22 – Duplicate share
23 – Redirected path
24 – Unknown device or directory
25 – Net name not found

Related

How to determine if the "Active Directory Domain Services" role has been installed on a server

I am trying to figure out if the Active Directory Domain Services are installed a windows server.
I know they show up in the Server Manager, but can I programmatically get if the role is installed on a server using C# code
If you know the name of the server you want to test and can run the program with domain admin privileges remotely, you can use WMI:
internal static bool IsDomainController(string ServerName)
{
StringBuilder Results = new StringBuilder();
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("\\\\" + ServerName + "\\root\\CIMV2",
"SELECT * FROM Win32_ServerFeature WHERE ID = 10");
foreach (ManagementObject queryObj in searcher.Get())
{
Results.AppendLine(queryObj.GetPropertyValue("ID").ToString());
}
}
catch (ManagementException)
{
//handle exception
}
if (Results.Length > 0)
return true;
else
return false;
}
If you're running that locally on the server, the WMI path changes to:
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_ServerFeature WHERE ID = 10");
See the MSDN reference on Win32_ServerFeature for a full list of roles and their ID numbers.
If your question is to see if a server is a domain controller, you can enumerate the domain controllers in the domain and check the hostname of the server you are sitting on to see if it matches any of them. To get the list of domain controllers:
var domainControllers = new List<string>();
var domain = Domain.GetCurrentDomain();
foreach (var dc in domain.DomainControllers)
{
domainControllers.Add(dc.Name);
}
string whoami = Dns.GetHostname();
Make sure to add requisite error handling (like if you run this on a workgroup computer, it will die).
EDIT:
Alternate ways of detecting DCPROMO (because it's possible to install Domain Services without DCPROMO, and that is a bad thing):
1) Parse out (and check for the existence of) the debug log that is created when DCPROMO does its thing. Should be located at c:\windows\debug\dcpromo.log
2) This DSQUERY command is FAST and will give you all the servers where DCPROMO was ran:
dsquery * "cn=Sites,cn=Configuration,dc=MyDomain,dc=com" -Filter "(cn=NTDS Settings)" -attr distinguishedName whenCreated
Problem is getting that from command line output if you started it using Process. Working on a way to do this and will update once I have it tested, as I haven't done AD filtering in a query for a while.

C# WMI Error Message "Not Supported"

I'm trying to install/add a networked printer on a remote computer using WMI. The below code works perfectly when i enter my local computer name but i get an error message "Not Supported" when i use any remote computer name. I looked up the WMI Error on MSDN and read "Feature or operation is not supported." But also noticed on MSDN they have a 'howto' add a new printer connection to a remote computer and there VBs example. I copied the VBs example and ran it and also recieved the same error "Not Supported". What am i missing? Any idea on what I'm doing wrong?
ConnectionOptions conOp = new ConnectionOptions();
conOp.Impersonation = ImpersonationLevel.Impersonate;
conOp.Authentication = AuthenticationLevel.Default;
conOp.EnablePrivileges = true;
ManagementScope manScope = new ManagementScope(#"\\pcname\ROOT\CIMV2", conOp);
manScope.Connect();
ManagementClass manClass = new ManagementClass(manScope, new ManagementPath("Win32_Printer"), null);
ManagementBaseObject inParams = manClass.GetMethodParameters("AddPrinterConnection");
inParams["Name"] = #"\\server\printer";
////////Error Occurs Here
ManagementBaseObject outParams = manClass.InvokeMethod("AddPrinterConnection", inParams, null);

Remote running msiexec on Win32_Process

The main task of this short part is get some computer name and install on this PC needed software (throught msiexec.exe)
I do this
{
Credential creds = new Credential();
UserAttr UserCredential = new UserAttr();
UserCredential = creds.DefaultFlagsTest();
ConnectionOptions connection = new ConnectionOptions();
connection.Username = UserCredential.UserName;
connection.Password = UserCredential.password;
connection.Authentication = AuthenticationLevel.PacketPrivacy;
connection.Authority = "ntlmdomain:tcc1";
ManagementScope scope = new ManagementScope(
"\\\\"+computerName+"\\root\\CIMV2", connection);
scope.Connect();
ManagementClass classInstance =
new ManagementClass(scope,
new ManagementPath("Win32_Process"), null);
ManagementBaseObject inParams = classInstance.GetMethodParameters("Create");
inParams["CommandLine"] = #"msiexec.exe /qb /m log.mif /i ""\\tcc1-pgh10.tcc1.local\swshare$\Packages\NetAgent_10.0.3361\exec\Kaspersky Network Agent.msi""";
ManagementBaseObject outParams = classInstance.InvokeMethod("Create", inParams, null);
int res = int.Parse(outParams["ReturnValue"].ToString());
if (res == 0)
{
MessageBox.Show(outParams["ReturnValue"].ToString(), "Result");
}
else throw new System.ComponentModel.Win32Exception(res);
Close();
}
the program returns 0, but its doesnt mean that msiexec is complete with the same success. Error is check path of package .. or smth. But what i see in a log file log.mif:
..............................
START ATTRIBUTE
NAME = "Product"
ID = 2
ACCESS = READ-ONLY
STORAGE = SPECIFIC
TYPE = STRING(64)
VALUE = "\tcc1-pgh10.tcc1.local\swshare$\Packages\NetAgent_10.0.3361\exe"
END ATTRIBUTE
..............................
he crops the name of package at 64 symb. The reason is that parametr CommandLine of Win32_Process.Create has this limit.
I don't know how to overcome this...
Win32_Process.Create also has property CurrentDirectory, thath seems can solve this propblem. But he can't process UNC paths.
and i can't do the install directory shorter. it is not right. (And i can say that i've done this. And its worked)
Please, maybe you know how to solve this propblem with a long installation path?
different properties as TARGETDIR or INSTALLDIR set only path TO install, no FROM...
I gave up
START ATTRIBUTE
NAME = "Product"
ID = 2
ACCESS = READ-ONLY
STORAGE = SPECIFIC
TYPE = STRING(64)
VALUE = "\tcc1-pgh10.tcc1.local\swshare$\Packages\NetAgent_10.0.3361\exe"
END ATTRIBUTE
The value is limited to 64symb including path. It will be working properly only on a local machine without using UNC paths

Start process with WMI on remote machine from a share on another remote machine

I have the following code to run a process on a remote machine from a share on a second remote machine as described in the image:
(source: microsoft.com)
public class Runner
{
public static string RunExecutable(string machine, string executable, string username, string password, string domain)
{
try
{
ConnectionOptions connectionOptions = new ConnectionOptions();
connectionOptions.Authority = "kerberos:" + domain + #"\" + machine;
connectionOptions.Username = username;
connectionOptions.Password = password;
connectionOptions.Impersonation = ImpersonationLevel.Delegate;
connectionOptions.Authentication = AuthenticationLevel.PacketPrivacy;
//define the WMI root name space
ManagementScope scope = new ManagementScope(#"\\" + machine + "." + domain + #"\root\CIMV2", connectionOptions);
//define path for the WMI class
ManagementPath p = new ManagementPath("Win32_Process");
//define new instance
ManagementClass classInstance = new ManagementClass(scope, p, null);
ManagementClass startupSettings = new ManagementClass("Win32_ProcessStartup");
startupSettings.Scope = scope;
startupSettings["CreateFlags"] = 16777216;
// Obtain in-parameters for the method
ManagementBaseObject inParams = classInstance.GetMethodParameters("Create");
// Add the input parameters.
inParams["CommandLine"] = executable;
inParams["ProcessStartupInformation"] = startupSettings;
// Execute the method and obtain the return values.
ManagementBaseObject outParams = classInstance.InvokeMethod("Create", inParams, null);
// List outParams
string retVal = outParams["ReturnValue"].ToString();
return "ReturnValue: " + retVal;
}
catch (ManagementException me)
{
return me.Message;
}
catch (COMException ioe)
{
return ioe.Message;
}
}
}
I have 5 machines in my environment, all in the same domain. 3 are running Windows Server 2008R2, one Windows 7 and one Windows XP:
WinXP
Win7
Master2008
Slave2008-1
Slave2008-2
I run the code from Master2008, the domain controller, and try to start a process on the other machines, but run into some problems when starting a process on the XP and 7 machines.
When starting the process on the WinXP and Win7 machines i get a return value of 8, which is "Unknown error", but when starting the process on the Server 2008R2 machines it works without problems.
All the machines has been marked as trusted for delegation in AD.
The process I'm trying to start is \\"machine"\c$\Windows\System32\Calc.exe
I've tried running the process from different machines, and the result was the following (The program is beeing run on Master2008):
On WinXP
- From Win7: Failed (8)
- From Slave2008-1: Failed (8)
- From Slave2008-2: Failed (8)
- From Master2008: Failed (8)
On Win7
- From WinXP: Success (0)
- From Slave2008-1: Failed (8)
- From Slave2008-2: Failed (8)
- From Master2008: Failed (8)
On Slave2008-1
- From WinXP: Success (0)
- From Win7: Success (0)
- From Slave2008-2: Success (0)
- From Master2008: Success (0)
On Slave2008-2
- From WinXP: Success (0)
- From Win7: Success (0)
- From Slave2008-1: Success (0)
- From Master2008: Success (0)
For some reason, they all fail for WinXP machine, but the Win7 machine can install from the WinXP machine.
Does anyone have any idea what can be wrong?
It seems there were no problem with the code. I tried to make a simple application to start instead of "calc.exe" and it worked as it should.
The problem was that I was trying to start "calc.exe" from 64bit servers on a 32bit clients. Also, "calc.exe" on Windows7 wont run on WindowsXP.
Don't work.
http://technet.microsoft.com/en-us/library/ee156574.aspx
You cannot use the Delegate impersonation level unless all the user accounts and computer accounts involved in the transaction have all been marked as Trusted for delegation in Active Directory. This helps minimize the security risks. Although a remote computer can use your credentials, it can do so only if both it and any other computers involved in the transaction are trusted for delegation.

WMI + Bitlocker + C# Get encrypted Volumes produces timeout

i want to create a wrapper class for specific WMI functions that affect Bitlocker functionality. The first step is to get all the Bitlocker volumes of a machine so I created a Console Application and did this:
private static ManagementClass management;
private static ManagementObjectCollection Volumes = null;
static void Main(string[] args)
{
ManagementPath path = new ManagementPath();
path.Server = "";
path.NamespacePath = "\\ROOT\\CIMV2\\Security\\MicrosoftVolumeEncryption";
path.ClassName = "Win32_EncryptableVolume";
ConnectionOptions options = new ConnectionOptions();
options.Authentication = AuthenticationLevel.PacketPrivacy;
options.Impersonation = ImpersonationLevel.Impersonate;
ManagementScope scope = new ManagementScope(path, options);
ObjectGetOptions getOptions = new ObjectGetOptions();
management = new ManagementClass(scope, path, getOptions);
management.Get();
Volumes = management.GetInstances();
}
When I run this on a non-Bitlocker machine the Volumes Collection gets initialized OK, only that it has a Count of 0 of course. Now I copied the code over to a WinForms App and when I click a button to run this code it steps through OK but when I try to expand the collection during debugging the App hangs and I get a "Function evaluation timed out". It's the same code just in another Application. What could be the reason for this?
Hm. I got a null reference exception if I didn't run it as administrator, but when I ran it as administrator (Win 7 x64, btw), I got four Volumes back.
I just had a similar issue, I will post my code for you hopefully it helps.
ManagementObjectSearcher Encryption = new ManagementObjectSearcher(#"root\cimv2\Security\MicrosoftVolumeEncryption", "SELECT * FROM Win32_EncryptableVolume");
foreach (ManagementObject QueryObj in Encryption.Get())
{
string EncryptionStatus = QueryObj.GetPropertyValue("ProtectionStatus").ToString();
if (EncryptionStatus == "0")
{
EncryptionDialog.Text = "Unencrypted";
}
else if (EncryptionStatus == "1")
{
EncryptionDialog.Text = "Encrypted - SysPrep will not complete";
}
else if (EncryptionStatus == "2")
{
EncryptionDialog.Text = "Cannot Determine Encryption";
}
}
I'm using this to display the status for a sysprep tool i'm creating so the "EncryptionDialog.Text = ..." can be replaced with any other calls you may need. you also need to remember "which caused me issues at least" if you are using visual studio you will need to add a file to your project labeled "Application Manifest File" in the "Add New File" Dialog. The reason for this is that the application will need to be opened in Administrator mode(Just an FYI in case you haven't made it that far)

Categories

Resources