Programmatically setting the 'Connect as' user in IIS7 using C# - c#

I'm attempting to do this using the following code snippet, but the FindElement keeps giving me errors indicating it doesn't exist in the current context. Ultimately what I'm trying to do is set the username and password the website uses in the connect as area. This is different from the impersonation user.
using Microsoft.Web.Administration;
using Microsoft.Web.Management;
using Microsoft.Web.Media.TransformManager.Common;
using Microsoft.Web.Media.TransformManager;
using System.Web.Configuration;
using System.Collections;
Configuration config = iisManager.GetApplicationHostConfiguration();
ConfigurationSection sitesSection = config.GetSection("system.applicationHost/sites");
ConfigurationElementCollection sitesCollection = sitesSection.GetCollection();
ConfigurationElement siteElement = FindElement(sitesCollection, "site", "name", #"Default Web Site");
ConfigurationElementCollection applicationCollection = siteElement.GetCollection();
ConfigurationElement applicationElement = FindElement(applicationCollection, "application", "path", #"/MyNewVirtualDir");
ConfigurationElementCollection virtualDirCollection = applicationElement.GetCollection();
ConfigurationElement virtualDirElement = FindElement(virtualDirCollection, "virtualDirectory", "path", #"/");
virtualDirElement.Attributes["userName"].Value = "MYDOMAIN\\MyUser";
virtualDirElement.Attributes["password"].Value = "MyPassword";
EDIT : So as I was staring at the question after beating my head against this for a few days, I discovered you can accomplish this using ServerManager in the following context.
ServerManager iisManager = new ServerManager()
site = iisManager.Sites.FirstOrDefault(a => a.Name.Contains("Default"));
site.VirtualDirectoryDefaults.Password = tbImpersonatorPassword.Text;
site.VirtualDirectoryDefaults.UserName = tbImpersonatorUser.Text;

So as I was staring at the question after beating my head against this for a few days, and apparently you can accomplish this using Servermanager in the following context.
ServerManager iisManager = new ServerManager()
site = iisManager.Sites.FirstOrDefault(a => a.Name.Contains("Default"));
site.VirtualDirectoryDefaults.Password = tbImpersonatorPassword.Text;
site.VirtualDirectoryDefaults.UserName = tbImpersonatorUser.Text;

Setting the Username and Password on the VirtualDirectoryDefaults may not yield the results you are looking for. Instead you may want to locate the app within this Site object whose path is the root (hence the .Path.Equals("/") filter on the query), then modify that apps Virtual Directory username and password.
This can be accomplished with the following method (Please Note: this method assumes that you have already located the desired Site via a search on the ServerManagers Sites collection and that you are passing that Site object into this method). Be sure to dispose of the ServerManager object when you are done in order to avoid a memory leak.
public static void SetConnectAsAccount(Site site, string username, string password)
{
if (site == null)
{
throw new ArgumentNullException("site");
}
if (string.IsNullOrWhiteSpace(username))
{
throw new ArgumentNullException("username");
}
if (string.IsNullOrWhiteSpace(password))
{
throw new ArgumentNullException("password");
}
foreach (var app in site.Applications.Where(c => c.Path.Equals("/")))
{
try
{
// set the Connect-As Accounts login credentials to the Service Acount
var appVirDir = app.VirtualDirectories.Where(c => c.Path.Equals("/")).FirstOrDefault();
if (appVirDir != null)
{
appVirDir.UserName = username;
appVirDir.Password = password;
}
}
catch (Exception ex)
{
// log your exception somewhere so you know what went wrong
}
}
}

Related

C# Active Directory Search

I have this powershell function and i want to make it as a C# function.
How can i put it into C#?
Get-ADComputer -filter {Name -Like 'myComp'} -property * | select DistinguishedName
You should be able to do this quite easily. Add a reference to System.DirectoryServices.AccountManagement and then use this code:
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, 'YourDomain'))
{
ComputerPrincipal computer = ComputerPrincipal.FindByIdentity (ctx, "name");
if (computer != null)
{
// do whatever you need to do with your computer principal
string distinguishedName = computer.DistinguishedName;
}
}
Update: if you don't know your domain ........ - you can also use:
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
in which case the principal context is created for the current domain you're located in.
You can use C# in the following manner
Connect to the Domain controller and get the DomainContext
Use that to look up the computer objects based on a name.
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, Environment.UserDomainName)
{
using (PrincipalSearcher srch = new PrincipalSearcher(new ComputerPrincipal(ctx) { Name = "ServerName"}))
{
return srch.FindAll().Cast<ComputerPrincipal>().ToList().Select(x => x.DistinguishedName);
}
}
Above returns a list of DistinguishedNames that matches the Server Name.
All the other answers suggest using the System.DirectoryServices.AccountManagement namespace. While that will work, it is really just a wrapper around the System.DirectoryServices namespace to make things a bit easier to use. It does make things easier (sometimes) but it does so at the cost of performance.
For example, in all the examples you've been given, your code will retrieve every attribute with a value from the computer object in AD, even though you only want one attribute.
If you use DirectorySearcher, you can make the search and retrieve only that one attribute that you want:
public string GetComputerDn(string computerName) {
var searcher = new DirectorySearcher {
Filter = $"(&(objectClass=computer)(sAMAccountName={computerName}$))",
PropertiesToLoad = { "distinguishedName" } //return only the distinguishedName attribute
};
var result = searcher.FindOne();
if (result == null) return null;
return (string) result.Properties["distinguishedName"][0];
}
Note that in AD, the sAMAccountName of computer objects is what you would normally refer to as the "computer name", followed by $, which is why the filter is what it is.
Please try this:
Add reference to Active Directory Services (%programfiles%\Reference Assemblies\Microsoft\Framework.NETFramework\\System.DirectoryServices.AccountManagement.dll)
public string GetComputerName(string computerName)
{
using (var context = new PrincipalContext(ContextType.Domain, "your domain name goes here"))
{
using (var group = GroupPrincipal.FindByIdentity(context, "Active Directory Group Name goes here"))
{
var computers = #group.GetMembers(true);
return computers.FirstOrDefault(c => c.Name == computerName).DistinguishedName;
}
}
return null; // or return "Not Found"
}

Credentials - Microsoft reporting library

I have problem with Microsoft.Reporting library. I need to access SQL reporting services and I have report name, address of the server and username and password. First of all I need to get all parameters needed for one specific report.
Here is my implementation so far :
using System;
using System.Collections.Generic;
using Microsoft.Reporting.WinForms;
namespace ConsoleApp1
{
class Program
{
static IEnumerable<DataSourceCredentials> CredentialsEnumerable()
{
var credentials = new DataSourceCredentials
{
Name = #"domain\account",
Password = #"password"
};
yield return credentials;
}
static void Main(string[] args)
{
var credentials = new DataSourceCredentials
{
Name = #"domain\account",
Password = #"password"
};
var report = new ReportViewer
{
ProcessingMode = ProcessingMode.Remote
};
report.ServerReport.ReportPath = #"/Archiv/Daily sales";
report.ServerReport.ReportServerUrl = new Uri(#"http://serverIPaddress/reportserver");
report.ServerReport.SetDataSourceCredentials(credentials);
foreach (var param in report.ServerReport.GetParameters())
{
Console.WriteLine(param.ToString());
}
Console.ReadLine();
}
}
}
But I have problem with my code and mainly with :
report.ServerReport.SetDataSourceCredentials(credentials);
I am getting error, that it´s not possible to transfer from Microsoft.Reporting.WinForms.DataSourceCredentials to System.Collections.Generic.IEnumerable
I have already tryid to use variable "credentials" and created IEnumerable class but it´s not working.
Can you please suggest what is wrong with my code? How to fix it and provide credentials for reporting server? Without credentials I am getting error "Not authorized"
Thank you in advance
Problem solved - wrong credentials parameter.
Instead of :
report.ServerReport.SetDataSourceCredentials(credentials);
I used
report.ServerReport.ReportServerCredentials.NetworkCredentials = credentials;
And it´s working !

Authenticating Website Members as Users in CKFinder v3

Before beginning this question, I should point out that my knowledge of ASP.NET & C# is pretty much nil.
I'm in the process of trying to integrate the ASP.NET version of CKFinder v3 into a site built in a different language and all is going well so far; I have everything setup as I want it and it's working when I grant unrestricted access to CKF but I'm stuck at the point now of trying to restrict access to it by authenticating only certain members of my site to use it. All the pages that CKFinder appears on on my site are only accessible by those certain members but I need an extra level of security if, for example, anyone figures out the direct path to my "ckfinder.html" file.
In the ASP version of CKFinder, I simply added this line in the function that checks my member's privileges, where isEditor was a boolean whose value was assigned per member based on information from my database:
session("accessckf")=isEditor
and then edited the CheckAuthentication() function in CKFinder's "config.asp" file to read:
function CheckAuthentication()
CheckAuthentication=session("accessckf")
end function
Reading through this "Howto", authentication seems to be much more complex in v3 but, after a lot of trial and error and some help from Lesiman, I created this C# file, which is located in my CKF directory:
<%#page codepage="65001" debug="true" language="c#" lcid="6153"%>
<%#import namespace="CKSource.CKFinder.Connector.Core"%>
<%#import namespace="CKSource.CKFinder.Connector.Core.Authentication"%>
<%#import namespace="CKSource.CKFinder.Connector.Core.Builders"%>
<%#import namespace="CKSource.CKFinder.Connector.Host.Owin"%>
<%#import namespace="Owin"%>
<%#import namespace="System.Data.Odbc"%>
<%#import namespace="System.Threading"%>
<%#import namespace="System.Threading.Tasks"%>
<script runat="server">
public void Configuration(IAppBuilder appBuilder){
var connectorBuilder=ConfigureConnector();
var connector=connectorBuilder.Build(new OwinConnectorFactory());
appBuilder.Map("/path/to/connector",builder=>builder.UseConnector(connector));
}
public ConnectorBuilder ConfigureConnector(){
var connectorBuilder=new ConnectorBuilder();
connectorBuilder.SetAuthenticator(new MyAuthenticator());
return connectorBuilder;
}
public class MyAuthenticator:IAuthenticator{
public Task<IUser> AuthenticateAsync(ICommandRequest commandRequest,CancellationToken cancellationToken){
var domain=HttpContext.Current.Request.Url.Host;
var cookie=HttpContext.Current.Request.Cookies[urlDomain];
var password="";
var username="";
var user=new User(false,null);
if (cookie!=null){
if (cookie["username"]!=null)
username=cookie["username"];
if (cookie["password"]!=null)
password=cookie["password"];
if(username!=""&&password!=""){
var connection=new OdbcConnection("database=[database];driver=MySQL;pwd=[pwd];server=[server];uid=[uid];");
connection.Open();
OdbcDataReader records=new OdbcCommand("SELECT ISEDITOR FROM MEMBERS WHERE USERNAME='"+username+"' AND PASSWORD='"+password+"'",connection).ExecuteReader();
if(records.HasRows){
records.Read();
bool isEditor=records.GetString(0)=="1";
var roles="member";
if(isEditor)
roles="editor,member";
user=new User(isEditor,roles.Split(','));
}
records.Close();
connection.Close();
}
}
return Task.FromResult((IUser)user);
}
}
</script>
Loading that page produces no errors (which doesn't necessarily mean it's working as trying to write anything to screen from within the public class doesn't work, for some reason) so now I'm at the stage of somehow checking that file for authentication.
Originally, I had tried loading it via XMLHttp from within my function that checks membership privileges for the site but, as I suspected and as Lesmian confirmed, that wouldn't work. After more trial & error, I added code to check website member privileges to the C# file, which leads me to where I am now: stuck!
What do I need to edit within CKFinder in order to have it use this custom file to check whether or not a user is authenticated?
First you'll need a connector between the ASP's Session and CKFinder's .Net authenticator. Here's an example that serializes ASP Session contents into JSON.
Put the connector.asp into a publicly accessible location. http://myaspwebsite.com/connector.asp for example.
connector.asp
<%#Language=VBScript CodePage=65001%>
<% Option Explicit %>
<!--#include file="JSON.asp"-->
<%
' obtain JSON.asp from https://github.com/tugrul/aspjson/archive/master.zip
' just for testing, must be removed in the production environment
Session("isEditor") = True
Session("isMember") = True
' only local requests allowed
' instead of local and remote ip comparison, a secret key can be used
If Request.ServerVariables("LOCAL_ADDR") <> Request.ServerVariables("REMOTE_ADDR") Then
Response.Status = "403 Forbidden"
Response.End
End If
Response.ContentType = "application/json"
Response.Charset = "utf-8"
Dim JSONObject, Key
Set JSONObject = jsObject()
For Each Key In Session.Contents
If Not IsObject(Session.Contents(Key)) Then 'skip the objects cannot be serialized
JSONObject(Key) = Session.Contents(Key)
End If
Next
JSONObject.Flush
%>
CKFinder 3.3.0 comes with a default connector which can be found in /ckfinder/bin/CKSource.CKFinder.Connector.WebApp.dll, remove it.
Examine the following program and remember to replace builder.Map("/connector", SetupConnector); and new Uri("http://myaspwebsite.com/connector.asp"); with your own values.
It simply authenticates the users by checking ASP Session varaibles isEditor and isMember via connector.asp and finally claims the roles editor , member or none.
I assume that you have configured the roles editor and member in the web.config.
Then put the Shaggy.cs into /ckfinder/App_Code. Create App_Code directory if not exist. .Net files in this folder will be compiled on the fly.
For more information have a look at Shared Code Folders in ASP.NET Web Projects
Shaggy.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Newtonsoft.Json.Linq;
using Owin;
[assembly: Microsoft.Owin.OwinStartup(typeof(CKSource.CKFinder.Connector.Shaggy.Startup))]
namespace CKSource.CKFinder.Connector.Shaggy
{
using FileSystem.Local;
using FileSystem.Dropbox;
using Core;
using Core.Authentication;
using Config;
using Core.Builders;
using Core.Logs;
using Host.Owin;
using Logs.NLog;
using KeyValue.EntityFramework;
public class Startup
{
public void Configuration(IAppBuilder builder)
{
LoggerManager.LoggerAdapterFactory = new NLogLoggerAdapterFactory();
RegisterFileSystems();
builder.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "ApplicationCookie",
AuthenticationMode = AuthenticationMode.Active
});
//replace connector path with yours
builder.Map("/connector", SetupConnector);
}
private static void RegisterFileSystems()
{
FileSystemFactory.RegisterFileSystem<LocalStorage>();
FileSystemFactory.RegisterFileSystem<DropboxStorage>();
}
private static void SetupConnector(IAppBuilder builder)
{
var keyValueStoreProvider = new EntityFrameworkKeyValueStoreProvider("CacheConnectionString");
var authenticator = new ShaggysAuthenticator();
var connectorFactory = new OwinConnectorFactory();
var connectorBuilder = new ConnectorBuilder();
var connector = connectorBuilder
.LoadConfig()
.SetAuthenticator(authenticator)
.SetRequestConfiguration(
(request, config) =>
{
config.LoadConfig();
config.SetKeyValueStoreProvider(keyValueStoreProvider);
})
.Build(connectorFactory);
builder.UseConnector(connector);
}
}
public class ShaggysAuthenticator : IAuthenticator
{
// this method makes an http request on the background to gather ASP's all session contents and returns a JSON object
// if the request contains ASP's session cookie(s)
private static JObject GetAspSessionState(ICommandRequest requestContext)
{
// building Cookie header with ASP's session cookies
var aspSessionCookies = string.Join(";",
requestContext.Cookies.Where(cookie => cookie.Key.StartsWith("ASPSESSIONID"))
.Select(cookie => string.Join("=", cookie.Key, cookie.Value)));
if (aspSessionCookies.Length == 0)
{
// logs can be found in /ckfinder/App_Data/logs
LoggerManager.GetLoggerForCurrentClass().Info("No ASP session cookie found");
// don't make an extra request to the connector.asp, there's no session initiated
return new JObject();
}
//replace this URL with your connector.asp's
var publicAspSessionConnectorUrl = new Uri("http://myaspwebsite.com/connector.asp");
var localSafeAspSessionConnectorUrl = new UriBuilder(publicAspSessionConnectorUrl) { Host = requestContext.LocalIpAddress };
using (var wCli = new WebClient())
try
{
wCli.Headers.Add(HttpRequestHeader.Cookie, aspSessionCookies);
wCli.Headers.Add(HttpRequestHeader.Host, publicAspSessionConnectorUrl.Host);
return JObject.Parse(wCli.DownloadString(localSafeAspSessionConnectorUrl.Uri));
}
catch (Exception ex) // returning an empty JObject object in any fault
{
// logs can be found in /ckfinder/App_Data/logs
LoggerManager.GetLoggerForCurrentClass().Error(ex);
return new JObject();
}
}
public Task<IUser> AuthenticateAsync(ICommandRequest commandRequest, CancellationToken cancellationToken)
{
var aspSessionState = GetAspSessionState(commandRequest);
var roles = new List<string>();
var isEditor = aspSessionState.GetNullSafeValue("isEditor", false);
var isMember = aspSessionState.GetNullSafeValue("isMember", false);
if (isEditor) roles.Add("editor");
if (isMember) roles.Add("member");
var isAuthenticated = isEditor || isMember;
var user = new User(isAuthenticated, roles);
return Task.FromResult((IUser)user);
}
}
public static class JObjectExtensions
{
// an extension method to help case insensitive lookups with a default value to get avoid NullReferenceException
public static T GetNullSafeValue<T>(this JObject jobj, string key, T defaultValue = default(T))
{
dynamic val = jobj.GetValue(key, StringComparison.OrdinalIgnoreCase);
if (val == null) return defaultValue;
return (T)val;
}
}
}
Now you should have a working CKFinder connector. Change the logic in the method AuthenticateAsync if you need and see how CKFinder handles your Classic ASP membership management.
Did you setup your custom authentication provider with ConnectorBuilder?
public ConnectorBuilder ConfigureConnector()
{
var connectorBuilder = new ConnectorBuilder();
connectorBuilder.SetAuthenticator(new MyAuthenticator());
return connectorBuilder;
}
You can find full example here: http://docs.cksource.com/ckfinder3-net/configuration_by_code.html.
UPDATE
Additionally you should register ConnectorBuilder inside Startup class to add it to request pipeline:
public void Configuration(IAppBuilder appBuilder)
{
var connectorBuilder = ConfigureConnector();
var connector = connectorBuilder.Build(new OwinConnectorFactory());
appBuilder.Map("/CKFinder/connector", builder => builder.UseConnector(connector));
}
All this is from a documentation link I've provided before.

The current user has insufficient permissions to perform this operation. Add Termset in sharepoint

I am trying to bind a field to a termset, and if the termset does not exist I want to create it by code. However, even when the code is running with elevated privileges I get the following exception.
The current user has insufficient permissions to perform this operation.
public static void BindTaxonomyField(string taxonomyFieldId, string taxonomyNoteFieldId, string termSetName, string termGroup, SPWeb web)
{
try
{
if (web != null)
{
// get the taxonomyfield from the sitecollection
var field = web.Fields[new Guid(taxonomyFieldId)] as TaxonomyField;
if (field != null)
{
// attach the note field
field.TextField = new Guid(taxonomyNoteFieldId);
// set up the field for my termstore
var session = new TaxonomySession(web.Site);
if (session.TermStores.Count > 0)
{
// get termstore values
TermStore ts = session.TermStores[0];
Group group = GetGroup(termGroup, ts);
if (group == null)
{
ts.CreateGroup(termGroup);
//throw new Exception("Group was not found in the termstore");
}
// ReSharper disable PossibleNullReferenceException
TermSet termSet = group.TermSets.Any(s => s.Name == termSetName) ? group.TermSets[termSetName] : group.CreateTermSet(termSetName);
// ReSharper restore PossibleNullReferenceException
//TermSet termSet = group.TermSets[termSetName];
// actually setup the field for using the TermStore
field.SspId = ts.Id;
field.TermSetId = termSet.Id;
}
field.Update();
}
}
}
catch (Exception ex)
{
}
}
private void BindColumnsToTermStore(string url)
{
try
{
SPSecurity.RunWithElevatedPrivileges(delegate
{
using (var site = new SPSite(url))
{
using (SPWeb web = site.OpenWeb())
{
if (!web.AllowUnsafeUpdates)
web.AllowUnsafeUpdates = true;
BindTaxonomyField("EF810CD2-F2D2-4BD2-9ABF-C19815F13568",
"67E6E777-0D1E-4840-B858-17400CFABD14",
"Business Audience", "IctDocumentation",
web);
web.AllowUnsafeUpdates = false;
}
}
});
}
If you go in to central administration and navigate to your term store(this is in the left hand nav) in the main container of the page there is a box with a few usernames. Is the account you are running the code in listed? If not stick them in there.
i think the path is something like Central admin -> Manage service application -> Managed meta data service - and the are on the page is call Term store Administrators
There is also one more place you must check but check this first and them run again.
The next place to check is to highlight your Manage metadata service which is located
Central admin -> Manage service application
and click on permissions on the ribbon and make sure the users your running the code with has the correct access.
I always start by making sure i know who i am running the code as first of all then do the checks

Reading Group Policy Settings using C#

How do I go about iterating over available and/or set settings in a given GPO (using name or GUID) in an AD domain? Without having to export to XML/HTML using powershell, etc.
I'm using C# (.NET 4.0).
That question got me hyped so I went to research it. So a +1
Some solutions I found from the top being the best to bottom being the worst
A good explanation with an example and example script!
This one, tells you to go through the registry but you gotta figure out who to access the AD
Pinvoke: Queries for a group policy override for specified power settings.
I had a similar problem, and didn't want to download and install the Microsoft GPO library (Microsoft.GroupPolicy.Management). I wanted to do it all with System.DirectoryServices. It took a little digging, but it can be done.
First retrieve your container using DirectorySearcher. You'll need to have already opened a directory entry to pass into the searcher. The filter you want is:
string filter = "(&" + "(objectClass=organizationalUnit)" + "(OU=" + container + "))";
and the property you're interested in is named "gPLink", so create an array with that property in it:
string[] requestProperties = { "gPLink" };
Now retrieve the results, and pull out the gPLink, if available.
using (var searcher = new DirectorySearcher(directory, filter, properties, SearchScope.Subtree))
{
SearchResultCollection results = searcher.FindAll();
DirectoryEntry entry = results[0].GetDirectoryEntry();
string gpLink = entry.Properties["gPLink"].Value;
If gpLink is null, there is no GPO associated with the container (OU).
Otherwise, gpLink will contain a string such as this:
"[LDAP://cn={31B2F340-016D-11D2-945F-00C04FB984F9},cn=policies,cn=system,DC=Test,DC=Domain;0]"
In the text above, you can see a CN for the GPO. All we need to do now is retrieve the GPO from the DC.
For that, we use a filter that looks like this:
string filter = "(&" +
"(objectClass=groupPolicyContainer)" +
"(cn={31B2F340-016D-11D2-945F-00C04FB984F9}))";
You'll want to create a Properties array that include the following:
Properties = { "objectClass", "cn", "distinguishedName", "instanceType", "whenCreated",
"whenChanged", "displayName", "uSNCreated", "uSNChanged", "showInAdvancedViewOnly",
"name", "objectGUID", "flags", "versionNumber", "systemFlags", "objectCategory",
"isCriticalSystemObject", "gPCFunctionalityVersion", "gPCFileSysPath",
"gPCMachineExtensionNames", "dSCorePropagationData", "nTSecurityDescriptor" };
Now use DirectorySearcher to retrieve the GPO. You'll get back a DirectoryEntry in the results that contains all of the above fields in the Properties collection. Some are COM objects, so you'll have to handle those appropriately.
Here is a better and more complete example then above.
class Program
{
static void Main(string[] args)
{
DirectoryEntry rootDse = new DirectoryEntry("LDAP://rootDSE");
DirectoryEntry root = new DirectoryEntry("GC://" + rootDse.Properties["defaultNamingContext"].Value.ToString());
DirectorySearcher searcher = new DirectorySearcher(root);
searcher.Filter = "(objectClass=groupPolicyContainer)";
foreach (SearchResult gpo in searcher.FindAll())
{
var gpoDesc = gpo.GetDirectoryEntry().Properties["distinguishedName"].Value.ToString();
Console.WriteLine($"GPO: {gpoDesc}");
DirectoryEntry gpoObject = new DirectoryEntry($"LDAP://{gpoDesc}");
try
{
Console.WriteLine($"DisplayName: {gpoObject.Properties["displayName"].Value.ToString()}");
}
catch
{
}
try
{
Console.WriteLine($"PCFileSysPath: {gpoObject.Properties["gPCFileSysPath"].Value.ToString()}");
}
catch
{
}
try
{
Console.WriteLine($"VersionNumber: {gpoObject.Properties["versionNumber"].Value.ToString()}");
}
catch
{
}
try
{
Console.WriteLine($"UserExtensionNames: {gpoObject.Properties["gPCUserExtensionNames"].Value.ToString()}");
}
catch
{
}
try
{
Console.WriteLine($"MachineExtensionNames: {gpoObject.Properties["gPCMachineExtensionNames"].Value.ToString()}");
}
catch
{
}
try
{
Console.WriteLine($"PCFunctionality: {gpoObject.Properties["gPCFunctionalityVersion"].Value.ToString()}");
}
catch
{
}
}
Console.ReadKey();
}
}
UPDATED: Working copy. You can now use c# to get read and parse a given GPO without having to use Powershell or write anything to disk.
using Microsoft.GroupPolicy;
var guid = new Guid("A7DE85DE-1234-F34D-99AD-5AFEDF7D7B4A");
var gpo = new GPDomain("Centoso.local");
var gpoData = gpo.GetGpo(guid);
var gpoXmlReport = gpoData.GenerateReport(ReportType.Xml).ToString();
using (XmlReader reader = XmlReader.Create(new StringReader(gpoXmlReport)))
{
string field;
while (reader.MoveToNextAttribute())
{
foreach (string attr in attributes)
{
// do something
}
}
}
This uses the Group Policy Management Console (GPMC) tools:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa814316(v=vs.85).aspx
Microsoft.GroupPolicy Namespace
https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.grouppolicy(v=vs.85).aspx

Categories