Enabling filestream with WMI and C# - c#

I have need to enable FILESTREAM on a SQL Server through a program. According to documentation I have found, this can be done through WMI with the following code:
set fsInstance = GetObject("WINMGMTS:\\" & MachineName & "\root\Microsoft\SqlServer\ComputerManagement10:FilestreamSettings='" & InstanceName & "'")
Set method = fsInstance.Methods_("EnableFilestream")
Set inParam = method.inParameters.SpawnInstance_()
inParam.AccessLevel = TargetLevel
inParam.ShareName = ShareName
Set outParam = fsInstance.ExecMethod_("EnableFilestream", inParam)
Converting this to C#, I get the following:
ManagementClass mc = new ManagementClass(new ManagementScope(#"\\.\root\Microsoft\SqlServer\ComputerManagement10"),
new ManagementPath("FilestreamSettings"),
new ObjectGetOptions(new ManagementNamedValueCollection() {
{"InstanceName", "MSSQLSERVER"}
}));
ManagementBaseObject inParams = mc.GetMethodParameters("EnableFilestream");
inParams["AccessLevel"] = 1;
inParams["ShareName"] = "ALLIANCE";
mc.InvokeMethod("EnableFilestream", inParams, null);
Whenever I try this, though, it throws an exception on InvokeMethod. The message is "Invalid method parameter(s)". I have attempted to remove the two lines where I set AccessLevel and ShareName and run it that way, but get the same exception. What am I doing wrong here?

Related

how to print Test page on a Printer?

I am new to C# and I am using windows forms, windows 7 and .Net 4.0.
I have 3 printers connected to my computer I want to print windows test page on a specific printer. All printers names are listed in ComboBox as shown in the following code I want to select a printer from ComboBox and print test page.
I had a look Here, Here and Here but nothing helped.
Does anyone know how to do it?
foreach (string printer in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
{
comboBox_Printers.Items.Add(printer);
}
Now, this method might look verbose, but I think it's important, when calling WMI methods, that the Management Options and Scopes are defined correctly.
This gives means to correct/adapt the code to specific contexts, when necessary.
Also, the helper methods here can be reused to initialize any other WMI query.
For example, a wrong Impersonation option, will result in an exception (0x80070005: (E_ACCESSDENIED)) when connecting to the WMI Scope or when the WMI query is executed.
A description of the PrintTestPage method parameters:
string PrinterName: the name of a specific Printer or null to use the default Printer.
string MachineName: the name of a Machine in the Network or null to use the LocalMachine name.
The method returns 0 if successful and throws an exception if the Printer is not found.
Sample call to Print a test page using the default printer in the local machine:
var result = PrintTestPage(null, null);
using System.Linq;
using System.Management;
public static uint PrintTestPage(string PrinterName, string MachineName)
{
ConnectionOptions connOptions = GetConnectionOptions();
EnumerationOptions mOptions = GetEnumerationOptions(false);
string machineName = string.IsNullOrEmpty(MachineName) ? Environment.MachineName : MachineName;
ManagementScope mScope = new ManagementScope($#"\\{machineName}\root\CIMV2", connOptions);
SelectQuery mQuery = new SelectQuery("SELECT * FROM Win32_Printer");
mQuery.QueryString += string.IsNullOrEmpty(PrinterName)
? " WHERE Default = True"
: $" WHERE Name = '{PrinterName}'";
mScope.Connect();
using (ManagementObjectSearcher moSearcher = new ManagementObjectSearcher(mScope, mQuery, mOptions))
{
ManagementObject moPrinter = moSearcher.Get().OfType<ManagementObject>().FirstOrDefault();
if (moPrinter is null) throw new InvalidOperationException("Printer not found");
InvokeMethodOptions moMethodOpt = new InvokeMethodOptions(null, ManagementOptions.InfiniteTimeout);
using (ManagementBaseObject moParams = moPrinter.GetMethodParameters("PrintTestPage"))
using (ManagementBaseObject moResult = moPrinter.InvokeMethod("PrintTestPage", moParams, moMethodOpt))
return (UInt32)moResult["ReturnValue"];
}
}
Helper methods:
private static EnumerationOptions GetEnumerationOptions(bool DeepScan)
{
EnumerationOptions mOptions = new EnumerationOptions()
{
Rewindable = false, //Forward only query => no caching
ReturnImmediately = true, //Pseudo-async result
DirectRead = true, //Skip superclasses
EnumerateDeep = DeepScan //No recursion
};
return mOptions;
}
private static ConnectionOptions GetConnectionOptions()
{
ConnectionOptions connOptions = new ConnectionOptions()
{
EnablePrivileges = true,
Timeout = ManagementOptions.InfiniteTimeout,
Authentication = AuthenticationLevel.PacketPrivacy,
Impersonation = ImpersonationLevel.Impersonate
};
return connOptions;
}

Create VM with WMI in c#

I am trying to create a VM in Hyper-V with WMI.
ManagementClass virtualSystemManagementService =
new ManagementClass(#"root\virtualization\v2:Msvm_VirtualSystemManagementService");
ManagementBaseObject inParams =
virtualSystemManagementService
.GetMethodParameters("DefineSystem");
// Add the input parameters.
ManagementClass virtualSystemSettingData =
new ManagementClass(#"root\virtualization\v2:Msvm_VirtualSystemSettingData")
{
["ElementName"] = "Test"
};
inParams["SystemSettings"] =
virtualSystemSettingData.GetText(TextFormat.CimDtd20);
// Execute the method and obtain the return values.
ManagementBaseObject outParams =
virtualSystemManagementService
.InvokeMethod("DefineSystem", inParams, null);
The call to InvokeMethod throws an System.Management.MangementException - "Invalid method Parameter(s).
I am basing this code on https://blogs.msdn.microsoft.com/virtual_pc_guy/2013/06/20/creating-a-virtual-machine-with-wmi-v2/
I do realize that this is really easy with powershell, but I am trying to understand how the WMI side of things works.
Basic workflow For Virtual Machine Creation using WMI with C#:
You missed creating an instance of VirtualSystemSettingData and getting an instance of VirtualSystemManagment Service.
The exception System.Management.MangementException - "Invalid method Parameter(s) is thrown when you call invoke method on a class not an object!
Create VirtualSystemSettingData class
Add Properties
Create new VirtualSystemSettingData instance
Convert to text
Pass to params
Create VirtualSystemManagementService class
Get existing VirtualSystemManagementService instance
Invoke Method
Example:
ManagementClass virtualSystemManagementServiceClass =
new ManagementClass(#"root\virtualization\v2:Msvm_VirtualSystemManagementService");
ManagementBaseObject inParams =
virtualSystemManagementServiceClass
.GetMethodParameters("DefineSystem");
// Add the input parameters.
ManagementClass virtualSystemSettingDataClass =
new ManagementClass(#"root\virtualization\v2:Msvm_VirtualSystemSettingData")
{
["ElementName"] = "Test"
};
// Create Instance of VirtualSystemSettingData
ManagementObject virtualSystemSettingData = virtualSystemSettingDataClass.CreateInstance();
inParams["SystemSettings"] =
virtualSystemSettingData.GetText(TextFormat.CimDtd20);
// Get Instance of VirtualSystemManagmentService
ManagementObject virtualSystemManagementService = null;
foreach (ManagementObject instance in virtualSystemManagementServiceClass.GetInstances())
{
virtualSystemManagementService = instance;
break;
}
// Execute the method and obtain the return values.
ManagementBaseObject outParams = virtualSystemManagementService.InvokeMethod("DefineSystem", inParams, null);
You need to create an instance of msvm_VirtualSystemSettingData.
ManagementObject newInstance = new ManagementClass(scope, new ManagementPath("Msvm_VirtualSystemSettingData"), null).CreateInstance();
newInstance["ElementName"] = vmName;
inParameters["SystemSettings"] = newInstance.GetText(TextFormat.CimDtd20);

Applying a snapshot in Hyper-V WMI V2 from C#

I am trying to replicate the following PowerShell in C#:
# Details from here are not particularly important but needed for full sample
$vms = gwmi -namespace "root\virtualization\v2" Msvm_ComputerSystem
$vm = $vms[3]
$snapshot = ($vm.GetRelated("Msvm_VirtualSystemSettingData") | Where { $_.ElementName -eq "SnapshotName" })[0]
# end unimportant
$VMSS = Get-WMiObject -class Msvm_VirtualSystemSnapshotService -namespace root\virtualization\v2
$VMSS.ApplySnapshot($snapshot, $null)
This code works fine - the snapshot applies as expected.
I have no problem getting the Msvm_VirtualSystemSettingData instance or a Msvm_VirtualSystemSnapshostService instance in C#. However, I can't seem to get the call to ApplySnapshot right - no matter what I give it I get an InvalidOperationException. I'm using generated WMI code from Visual Studio for the call:
public uint ApplySnapshot(ref System.Management.ManagementPath Job, System.Management.ManagementPath Snapshot) {
if ((isEmbedded == false)) {
System.Management.ManagementBaseObject inParams = null;
inParams = PrivateLateBoundObject.GetMethodParameters("ApplySnapshot");
// following line has been through variations as well with no change -
// commenting it out, setting to null
inParams["Job"] = ((System.Management.ManagementPath)(Job)).Path;
inParams["Snapshot"] = ((System.Management.ManagementPath)(Snapshot)).Path;
System.Management.ManagementBaseObject outParams = PrivateLateBoundObject.InvokeMethod("ApplySnapshot", inParams, null);
Job = ((System.Management.ManagementPath)(outParams.Properties["Job"].Value));
return System.Convert.ToUInt32(outParams.Properties["ReturnValue"].Value);
}
else {
return System.Convert.ToUInt32(0);
}
}
I'm not sure what to pass for the Job parameter either, since we get a job back - it's very unusual to have a ref for that instead of an out but I've tried a bunch of different variations around that (including setting the parameter to null and not setting it at all) with no luck. I've also tried setting inParams[Job] to null with no luck for that either.
What should I change to make this work?
I believe your problem is that you are passing in the job to start with when it is an outbound parameter. That parameter will return from the invocation. Something like..
ManagementBaseObject inParams = null;
inParams = PrivateLateBoundObject.GetMethodParameters("ApplySnapshot");
inParams["Snapshot"] = ((System.Management.ManagementPath)(Snapshot)).Path;
ManagementBaseObject outParams = PrivateLateBoundObject.InvokeMethod("ApplySnapshot", inParams, null);
// i left this as i assume this is vs generated though this isn't how i would normally
// get my jobs back.
Job = ((ManagementPath)(outParams.Properties["Job"].Value));
return Convert.ToUInt32(outParams.Properties["ReturnValue"].Value);

Using WMI to create active directory dns zones

I'm using the following code to create a DNS zone:
ManagementClass zoneObj = new ManagementClass(session, new ManagementPath("MicrosoftDNS_Zone"), null);
ManagementBaseObject inParams = zoneObj.GetMethodParameters("CreateZone");
inParams["ZoneName"] = "thedomain.com";
inParams["ZoneType"] = 0;
ManagementBaseObject outParams = zoneObj.InvokeMethod("CreateZone", inParams, null);
This creates the zone, but creates it with the type "Standard Primary". I need it to create with the type "Active Directory - Integrated Primary". From all my research, the zone type of "0" should do this. Can anyone tell me why it won't create the zone as an active directory zone?
I figured it out. Anyone else with the same issue, you have to add the DsIntegrated parameter to tell it to use Active Directory. Here is the final code:
ManagementClass zoneObj = new ManagementClass(session, new ManagementPath("MicrosoftDNS_Zone"), null);
ManagementBaseObject inParams = zoneObj.GetMethodParameters("CreateZone");
inParams["ZoneName"] = "thedomain.com";
inParams["ZoneType"] = 0;
inParams["DsIntegrated"] = true; //--- this is what needed to be added
ManagementBaseObject outParams = zoneObj.InvokeMethod("CreateZone", inParams, null);
DsIntegrated
Indicates whether zone data is stored in the Active Directory or in files. If TRUE, the data is stored in the Active Directory; if FALSE, the data is stored in files.

How to add a DNS alias programmatically?

I want to create an alias record in Microsoft's DNS server to point AliasA to ComputerA. How can I do this programmatically?
I used WMI to do this, found an example on the web, and this is what it looked like.
private ManagementScope _session = null;
public ManagementPath CreateCNameRecord(string DnsServerName, string ContainerName, string OwnerName, string PrimaryName)
{
_session = new ManagementScope("\\\\" + DnsServerName+ "\\root\\MicrosoftDNS", con);
_session.Connect();
ManagementClass zoneObj = new ManagementClass(_session, new ManagementPath("MicrosoftDNS_CNAMEType"), null);
ManagementBaseObject inParams = zoneObj.GetMethodParameters("CreateInstanceFromPropertyData");
inParams["DnsServerName"] = ((System.String)(DnsServerName));
inParams["ContainerName"] = ((System.String)(ContainerName));
inParams["OwnerName"] = ((System.String)(OwnerName));
inParams["PrimaryName"] = ((System.String)(PrimaryName));
ManagementBaseObject outParams = zoneObj.InvokeMethod("CreateInstanceFromPropertyData", inParams, null);
if ((outParams.Properties["RR"] != null))
{
return new ManagementPath(outParams["RR"].ToString());
}
return null;
}
I don't think .NET has anything to provide access to these (all I can find in a bit of quick searching is references to proprietary libraries, controls, etc.), so you'll probably have to use the Win32 API via P/Invoke (though another possibility would be to do the job via WMI).
You'd start with DnsAcquireContextHandle, then (probably) DnsQuery to get a current record set, modify its contents to add your new alias, DnsReplaceRecordSet to have the DNS server use the new set of records, and finally DnsReleaseContextHandle to shut things down.
Of course, you'll need the right permissions on the server or none of this will work at all.

Categories