How can I use WMIUserID, WMIPassword, WMIAlternateCredentials using C#?
Also, is it possible to get remote computer's Administrator-password?
Please try to explain with examples.
Thanks.
Her is some example code
using System;
using System.Text;
using System.Threading;
using Microsoft.Management.Infrastructure;
using Microsoft.Management.Infrastructure.Options;
using System.Security;
namespace SMAPIQuery
{
class Program
{
static void Main(string[] args)
{
string computer = "Computer_B";
string domain = "DOMAIN";
string username = "AdminUserName";
string plaintextpassword;
Console.WriteLine("Enter password:");
plaintextpassword = Console.ReadLine();
SecureString securepassword = new SecureString();
foreach (char c in plaintextpassword)
{
securepassword.AppendChar(c);
}
// create Credentials
CimCredential Credentials = new CimCredential(PasswordAuthenticationMechanism.Default,
domain,
username,
securepassword);
// create SessionOptions using Credentials
WSManSessionOptions SessionOptions = new WSManSessionOptions();
SessionOptions.AddDestinationCredentials(Credentials);
// create Session using computer, SessionOptions
CimSession Session = CimSession.Create(computer, SessionOptions);
var allVolumes = Session.QueryInstances(#"root\cimv2", "WQL", "SELECT * FROM Win32_Volume");
var allPDisks = Session.QueryInstances(#"root\cimv2", "WQL", "SELECT * FROM Win32_DiskDrive");
// Loop through all volumes
foreach (CimInstance oneVolume in allVolumes)
{
// Show volume information
if (oneVolume.CimInstanceProperties["DriveLetter"].ToString()[0] > ' ' )
{
Console.WriteLine("Volume ‘{0}’ has {1} bytes total, {2} bytes available",
oneVolume.CimInstanceProperties["DriveLetter"],
oneVolume.CimInstanceProperties["Size"],
oneVolume.CimInstanceProperties["SizeRemaining"]);
}
}
// Loop through all physical disks
foreach (CimInstance onePDisk in allPDisks)
{
// Show physical disk information
Console.WriteLine("Disk {0} is model {1}, serial number {2}",
onePDisk.CimInstanceProperties["DeviceId"],
onePDisk.CimInstanceProperties["Model"].ToString().TrimEnd(),
onePDisk.CimInstanceProperties["SerialNumber"]);
}
Console.ReadLine();
}
}
}
Related
In order to get information about Serial Port devices, with System.Management, we can do as described in Getting Serial Port Information:
using System;
using System.Management;
using System.Collections.Generic;
using System.Linq;
using System.IO.Ports;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
using (var searcher = new ManagementObjectSearcher
("SELECT * FROM WIN32_SerialPort"))
{
string[] portnames = SerialPort.GetPortNames();
var ports = searcher.Get().Cast<ManagementBaseObject>().ToList();
var tList = (from n in portnames
join p in ports on n equals p["DeviceID"].ToString()
select n + " - " + p["Caption"]).ToList();
tList.ForEach(Console.WriteLine);
}
// pause program execution to review results...
Console.WriteLine("Press enter to exit");
Console.ReadLine();
}
}
}
How can this be achieved using Microsoft.Management.Infrastructure, I haven't managed to find examples and the documentation isn't detailed enough.
It's quite similar:
Create a CimSession, where you specify the ComputerName (null for LocalHost) and a CimCredential object (passing the usual UserName and Password for authentication, is necessary). This reflects System.Management's ConnectionOption.
Use the CimSession's QueryInstances method to build the query, passing the namespace and the class. This reflects System.Management's SelectQuery and ManagementObjectSearcher
QueryInstances() returns an IEnumerble<CimInstance> objects (the good news is that no COM objects are returned here).
Get the Value of the CimInstanceProperties you care about.
As a note, you're skipping the ConnectionOption and EnumerationOptions in your WMI Query, which is not really good PERF-wise.
Your query can then be translated to:
using Microsoft.Management.Infrastructure;
using Microsoft.Management.Infrastructure.Options;
using (var session = CimSession.Create(null) {
var ports = session.QueryInstances(#"root\cimv2", "WQL", "SELECT * FROM WIN32_SerialPort");
string[] portnames = SerialPort.GetPortNames();
var tList = (from n in portnames
join p in ports on n equals p.CimInstanceProperties["DeviceID"].Value
select n + " - " + p.CimInstanceProperties["Caption"].Value);
}
I'm not sure why you use string[] portnames = SerialPort.GetPortNames(); here.
You can just use the CimProperties:
using (var session = CimSession.Create(null)) {
var ports = session.QueryInstances(#"root\cimv2", "WQL", "SELECT * FROM WIN32_SerialPort");
var portsDescriptions = ports.Select(p =>
$"{p.CimInstanceProperties["DeviceID"].Value} - {p.CimInstanceProperties["Caption"].Value}");
// If you actually need to materialize a List<T>...
portsDescriptions.ToList().ForEach(Console.WriteLine);
}
Unrelated, but could be useful: I suggest to build some methods to create a CimSession with more options. For example:
public static CimSession CreateSession(string computerName)
=> CreateSession(computerName, string.Empty, string.Empty, null);
public static CimSession CreateSession(string computerName, string domain, string userName, SecureString password)
{
if (string.IsNullOrEmpty(computerName) ||
computerName.Equals("localhost", StringComparison.InvariantCultureIgnoreCase)) {
computerName = null;
}
var option = new CimSessionOptions();
if (password != null && password.Length > 0) {
option.AddDestinationCredentials(
new CimCredential(PasswordAuthenticationMechanism.Default, domain, userName, password));
}
return CimSession.Create(computerName, option);
}
So, instead of:
var session = CimSession.Create(null);
You can call it as:
// LocalHost, default permissions
var session = CreateSession(null);
Or pass domain, Username and Password (as Char*), if needed.
I'm new to coding and I've started working on a task in c#. I've to develop a code to get file information, like file type, file size, owner name for a given directory path input.
Now, to save time, I thought of building a dictionary in which I'll store all the SID and corresponding Owner information. And the code won't loop through to get owner name each time by converting SID for each file, instead it will get the SID for that file and map it to it's owner using the built dictionary. This dictionary will be built once and will be updated if any new owner joins.
Does anyone know how to create a dictionary that can be used separately.
Here's the code I'm working on --
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//using System.IO;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Diagnostics;
using System.Collections;
using Alphaleonis.Win32.Filesystem;
// Alpha is external library used to allow long paths.
namespace Get_SID_Owner_Info
{
internal class Program
{
private static void Main()
{
Console.Write("Please enter the Directory Path -- ");
string foldr = Console.ReadLine();
Console.Write("Please enter the result path location e.g. D:\\Nolder\\Outfile.csv -- ");
string outfile = Console.ReadLine();
//string foldr = "D:\\Ansys_Training";
//string outfile = "D:\\Get_SID_Owner.csv";
var watch = new System.Diagnostics.Stopwatch();
watch.Start();
int[] index = new int[1000000];
int i;
i = 0;
IdentityReference[] SID_store = new IdentityReference[1000000];
IdentityReference[] Owner_store = new IdentityReference[1000000];
if (File.Exists(outfile))
{
File.Delete(outfile);
}
// Create a new file
using (System.IO.StreamWriter sw = File.CreateText(outfile))
{
sw.WriteLine("{0},{1}", "SID", "Owner Name");
string[] files = System.IO.Directory.GetFiles(foldr);
DirectoryInfo tempWithoutMac = new DirectoryInfo(foldr);
foreach (FileInfo fi in tempWithoutMac.GetFiles())
{
// SID --
FileSecurity fs = File.GetAccessControl(fi.FullName);
IdentityReference SID = fs.GetOwner(typeof(SecurityIdentifier));
// Owner --
IdentityReference Owner = SID.Translate(typeof(NTAccount));
SID_store[i] = SID;
Owner_store[i] = Owner;
i = i + 1;
}
foreach (string d in System.IO.Directory.GetDirectories(foldr, "*", System.IO.SearchOption.AllDirectories))
{
tempWithoutMac = new DirectoryInfo(d);
foreach (FileInfo fi in tempWithoutMac.GetFiles())
{
// SID --
FileSecurity fs = File.GetAccessControl(fi.FullName);
IdentityReference SID = fs.GetOwner(typeof(SecurityIdentifier));
// Owner --
IdentityReference Owner = SID.Translate(typeof(NTAccount));
SID_store[i] = SID;
Owner_store[i] = Owner;
i = i + 1;
}
}
IdentityReference[] SID_store2 = new IdentityReference[i];
IdentityReference[] Owner_store2 = new IdentityReference[i];
for (int j = 0; j < i; j++)
{
SID_store2[j] = SID_store[j];
Owner_store2[j] = Owner_store[j];
}
var SID_Unique = SID_store2.Distinct().ToList(); // Contains Unique SID's for the given directory --
var Owner_Unique = Owner_store2.Distinct().ToList();
Dictionary<IdentityReference, IdentityReference> SID_Owner_Data = new Dictionary<IdentityReference, IdentityReference>();
for (int j = 0; j < SID_Unique.Count; j++) // SID to Owner conversion for the Unique SID's --
{
SID_Owner_Data.Add(SID_Unique[j], Owner_Unique[j]);
Console.WriteLine(SID_Unique[j]);
Console.WriteLine(Owner_Unique[j]);
}
Console.WriteLine(SID_Unique.Count);
for (int k = 0; k < SID_Unique.Count; k++)
{
sw.WriteLine("{0},{1}", SID_Unique[k], Owner_Unique[k]);
}
}
watch.Stop();
Console.WriteLine($"Execution Time: {watch.ElapsedMilliseconds} ms");
Console.ReadKey();
}
}
}
If I understand correctly, you want to be able to resolve an SID to its owner, but through a caching mechanism so that each SID is resolved only once. This is trivial to do with a ConcurrentDictionary and GetOrAdd.
ConcurrentDictionary<IdentityReference,IdentityReference> _cache = new ConcurrentDictionary<IdentityReference,IdentityReference>();
IdentityReference GetTranslationWithCache(IdentityReference SID)
{
return _cache.GetOrAdd( SID, () => SID.Translate(typeof(NTAccount));
}
In this example. GetOrAdd will search the cache for the SID and return the corresponding translation if it is found. If it is not found, the key is added to the dictionary and the delegate (() => SID.Translate) is called in order to populate its value. This makes it good for use as a cache. As a bonus, your dictionary is thread-safe, so you can populate it from multiple threads to improve performance, and still guarantee that the calls to Translate will only happen once per SID.
I'm trying to write contacts into an ADLDS ldap for using them as a phone book for a Yealink T48G. Sometimes the name of the contact includes some special characters like "ö", "ß" and "é". If these characters are contained in the fields "givenName" or "displayName" neither the phone nor the ldap client can show them correctly and instead show some other chars (for example "ö" -> "ö"), however the "name" and "dn" fields show these characters correctly.
If I insert the contactvalues via ADSI-Edit or any other tool, the phone shows the name correctly, but my application is no longer able to read the inserted special chars from givenName and shows some questionmark-boxes, however the dn and name fields are read correctly.
I've already tried using utf-8, utf-16, utf-32, iso-8859-1 and windows-1252 as encoding for my application.
So the question is how can I store these special characters using C# in the givenName property for an inetOrgPerson in an ADLDS instance?
shown correctly:
shown incorrectly:
My code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.DirectoryServices.Protocols;
using System.Net;
namespace LdapContacts
{
public class LdapClient
{
private LdapConnection connection;
public LdapClient(string host, int port, string distinguishedUsername, string password)
{
connection = new LdapConnection(new LdapDirectoryIdentifier(host, port));
connection.AuthType = AuthType.Basic;
connection.Credential = new NetworkCredential(distinguishedUsername, password);
connection.Bind();
}
public AddResponse SendAddRequest(string distinguishedName, List<DirectoryAttribute> attributes)
{
AddRequest request = new AddRequest(distinguishedName, attributes.ToArray());
return connection.SendRequest(request) as AddResponse;
}
public SearchResponse SendSearchRequest(string distinguishedName, string filter)
{
SearchRequest request = new SearchRequest();
request.DistinguishedName = distinguishedName;
request.Filter = filter;
request.Scope = SearchScope.Subtree;
return connection.SendRequest(request) as SearchResponse;
}
}
public class ContactsToLdap
{
private static void Main(string[] args)
{
LdapClient client = new LdapClient(Settings.LdapHost, Settings.LdapPort, Settings.LdapUsername, Settings.LdapPassword);
client.SendAddRequest("CN=Testöäüß,CN=Users,CN=testpart,DC=csdomain,DC=local", new List<DirectoryAttribute>()
{
new DirectoryAttribute("telephoneNumber", "0123456"),
new DirectoryAttribute("objectClass", "inetOrgPerson"),
new DirectoryAttribute("uid", "io3e"),
new DirectoryAttribute("givenName", "â é testnameöüÄß")
});
//distinguished name of contactsfolder
SearchResponse result = client.SendSearchRequest(Settings.LdapContactsFolder, "(objectClass=inetOrgPerson)");
foreach (SearchResultEntry sResult in result.Entries)
{
//display the index of the current entry
Console.Write((result.Entries.IndexOf(sResult) + 1) + ":\n");
foreach (DirectoryAttribute attribute in sResult.Attributes.Values)
{
//output the name of the attribute
Console.Write("\t" + attribute.Name + " = ");
for (int i = 0; i < attribute.Count; i++)
{
// convert the attribute to a string if it is an byte[]
// output if inserted with ADSI-Edit: ? ? testname????
// output if inserted with this code: â é testnameöüÄß
if (attribute[i].GetType().Equals(typeof(byte[])))
{
Console.Write(Encoding.UTF8.GetString((byte[])attribute[i]) + "; ");
}
else
{
Console.Write(attribute[i] + "; ");
}
}
Console.WriteLine();
}
Console.WriteLine();
}
}
}
}
The issue was resolved by setting the protocolversion that should be used to version 3.
connection = new LdapConnection(new LdapDirectoryIdentifier(host, port));
connection.SessionOptions.ProtocolVersion = 3;
If it is possible to integrate Google big query with C# console application?.
If yes how we can do, i searched over internet i could not find proper answer for that.
I want connection string format? I have created Client ID from Google Developer console how authentication has done? It is one time configuration or every time we need to login in google account to authenticate.
If there is any sample application to connect sample data it would be helpful.
Thanks,
Selvakumar S
Here's a working sample based on another question in StackOverflow:
using DotNetOpenAuth.OAuth2;
using Google.Apis.Authentication.OAuth2;
using Google.Apis.Authentication.OAuth2.DotNetOpenAuth;
using Google.Apis.Bigquery.v2;
using Google.Apis.Bigquery.v2.Data;
using Google.Apis.Util;
using System;
using System.Diagnostics;
using System.Collections.Generic;
namespace BigQueryConsole
{
public class BigQueryConsole
{
// Put your client ID and secret here (from https://developers.google.com/console)
// Use the installed app flow here.
// Client ID looks like "9999999.apps.googleusercontent.com"
static string clientId = "YOURCLIENTID";
static string clientSecret = "YOURSECRET";
// Project ID is in the URL of your project on the APIs Console
// Project ID looks like "999999";
static string projectId = "YOURPROJECTID";
// Query in SQL-like form
static string query = "SELECT state, count(*) from [publicdata:samples.natality] GROUP BY state ORDER BY state ASC";
public static void Main(string[] args)
{
// Register an authenticator.
var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description);
provider.ClientIdentifier = clientId;
provider.ClientSecret = clientSecret;
// Initiate an OAuth 2.0 flow to get an access token
var auth = new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthorization);
// Create the service.
var service = new BigqueryService(auth);
JobsResource j = service.Jobs;
QueryRequest qr = new QueryRequest();
qr.Query = query;
QueryResponse response = j.Query(qr, projectId).Fetch();
foreach (TableRow row in response.Rows)
{
List<string> list = new List<string>();
foreach (TableRow.FData field in row.F)
{
list.Add(field.V);
}
Console.WriteLine(String.Join("\t", list));
}
Console.WriteLine("\nPress enter to exit");
Console.ReadLine();
}
private static IAuthorizationState GetAuthorization(NativeApplicationClient arg)
{
// Get the auth URL:
IAuthorizationState state = new AuthorizationState(new[] { BigqueryService.Scopes.Bigquery.GetStringValue() });
state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);
Uri authUri = arg.RequestUserAuthorization(state);
// Request authorization from the user (by opening a browser window):
Process.Start(authUri.ToString());
Console.Write(" Authorization Code: ");
string authCode = Console.ReadLine();
Console.WriteLine();
// Retrieve the access token by using the authorization code:
return arg.ProcessUserAuthorization(authCode, state);
}
}
}
In your answer i could not able to add namespace
"using Google.Apis.Authentication.OAuth2.DotNetOpenAuth;"
But i manage to retrieve results from BigQuery using below code, you need to update Project Name, Project Id and Query.
Download Client ID (I am using Installed Application - Other category ) generate JSON file and add into your Debug folder.
using Google.Apis.Auth.OAuth2;
using System.IO;
using System.Threading;
using Google.Apis.Bigquery.v2;
using Google.Apis.Bigquery.v2.Data;
using System.Data;
using Google.Apis.Services;
using System;
namespace GoogleBigQuery
{
public class Class1
{
private static void Main()
{
UserCredential credential;
using (var stream = new FileStream("client_secrets.json", FileMode.Open,
FileAccess.Read))
{
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
new[] { BigqueryService.Scope.Bigquery },
"user", CancellationToken.None).Result;
}
// Create and initialize the Bigquery service. Use the Project Name value
// from the New Project window for the ApplicationName variable.
BigqueryService Service = new BigqueryService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "PROJECT NAME"
});
string query = "YOUR QUERY";
JobsResource j = Service.Jobs;
QueryRequest qr = new QueryRequest();
qr.Query = query;
DataTable DT = new DataTable();
int i = 0;
QueryResponse response = j.Query(qr, "PROJECT ID").Execute();
if (response != null)
{
int colCount = response.Schema.Fields.Count;
foreach (var Column in response.Schema.Fields)
{
DT.Columns.Add(Column.Name);
}
foreach (TableRow row in response.Rows)
{
DataRow dr = DT.NewRow();
for (i = 0; i < colCount; i++)
{
dr[i] = row.F[i].V;
}
DT.Rows.Add(dr);
}
}
else
{
Console.WriteLine("Response is null");
}
}
}
}
Thanks.
I am using the below code to create a instance in the hp cloud(or any openstack). I am having issues with determining the base url.There could be other errors and i would appreciate anybody seeing them also. So do i find out the base url. I had a look through the hp docs but to no avail ?! Also i am unsure of how to obtain the image id, i presume the flavor is 'small' etc?
using System;
using System.Web;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using net.openstack.Core.Domain;
using net.openstack.Providers.Rackspace;
namespace Openstack2
{
class Program
{
static void Main(string[] args)
{
Uri baseUrl = new Uri("https://horizon.hpcloud.com/auth/login/");
CloudIdentity cloudId = new CloudIdentity()
{
Username = "#####",
Password = "####"
};
CloudIdentityProvider cip = new CloudIdentityProvider(cloudId, baseUrl);
UserAccess ua = cip.Authenticate(cloudId);
CloudServersProvider provider = new CloudServersProvider(cloudId);
Metadata metaData = new Metadata(); // Add some metadata just because we can
metaData.Add("Description", "Example 4 - Getting Started");
string serverName = "Server a14";
string imageId = "###";
string flavorId = "standard.xsmall";
NewServer newServer = provider.CreateServer(serverName, imageId, flavorId,DiskConfiguration.Manual, metaData);
}
}
}
The above code is based on the rackspace sdk to connect to the hp cloud, so that could be an issue. But i also used the following code based on the other .net openstack api.:
var identityUrl = "https://horizon.hpcloud.com/auth/login/";
var imageUrl = "http://server:9292";
var username = "####";
var password = "###";
var cloudId = new CloudIdentity() { Username = username, Password = password };
var cloudIdProvider = new CloudIdentityProvider(new Uri(identityUrl));
cloudIdProvider.Authenticate(cloudId);
var cloudServersProvider = new CloudServersProvider(cloudId, cloudIdProvider);
var newServer = cloudServersProvider.CreateServer("Team 101 Server a14", "Team 101 Server a14", "standard.xsmall");
Still will not connect to my hp openstack. I think i will half to ditch c# and maybe go with powershell or nova.
i am using HP Cloud and this is how i get the baseUrl:
...
using HPCloud.Common;
using HPCloud.Objects;
using HPCloud.Objects.Utility;
using HPCloud.Objects.DataAccess;
using HPCloud.Objects.Domain;
using HPCloud.Objects.Domain.Compute;
using HPCloud.Objects.Domain.Admin;
session = Session.CreateSession("accessKey", "secretKey", "tennantID");
private Session session = null;
public static string GenerateUrl(Session session, string bucket_name, string key)
{
string baseUrl = session.Context.ServiceCatalog.GetService(HPCloud.Objects.Domain.Admin.Services.ObjectStorage).Url;
return baseUrl + "/" + bucket_name + "/" + key;
}
You will need to get accesskey, secretkey, and tennantID from your cloud admin page.
You may need to add HPCloud-API and BouncyCastle from Nuget.
so now you can use the following to drop a file in your cloud bucket:
public static bool PutFile(Session session, string bucket_name, string file_path, out string key)
{
if (!File.Exists(file_path))
{
throw new FileNotFoundException(file_path);
}
bool success = false;
key = System.IO.Path.GetFileName(file_path);
try
{
var soRepo = session.Factory.CreateStorageObjectRepository();
string fullUrl = GenerateUrl(session, bucket_name, key);
soRepo.Copy(file_path, fullUrl, false);
success = true;
}
catch
{
success = false;
key = string.Empty;
}
return success;
}