I am trying to change some windows settings by group policy settings using C#.
My application creates sub-keys in the group policy objects section successfully,
But some times they doesn't work.
For example i am trying to disable desktop using Group policy, I take these steps :
I run Process monitor and configure it to show me the registry changes relating to mmc.exe
Then run gpedit.msc and navigate to the desired option and change it
I copy the registry change which is shown in Process monitor and use it
in my app like this :
mmc.exe RegSetValue HKCU\Software\Microsoft\Windows\CurrentVersion\Group Policy Objects\{FD0F8A58-1909-410F-8860-4CFF7766FA89}User\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\NoDesktop SUCCESS Type: REG_DWORD, Length: 4, Data: 1
And use it like this :
string regPath = #"Software\Microsoft\Windows\CurrentVersion\Policies\Explorer";
string option = "NoDesktop";
SetGroupPolicySetting(regPath, option, 1);
SetGroupPolicySetting uses a dll which can be downloaded from here and is written like this :
private void SetGroupPolicySetting(string registryKeyPath,
string option,
int value ,
GroupPolicySection groupPolicySection = GroupPolicySection.User)
{
var gpo = new ComputerGroupPolicyObject();
RegistryKey registryKey = gpo.GetRootRegistryKey(groupPolicySection);
registryKey.CreateSubKey(registryKeyPath).SetValue(option, value , RegistryValueKind.DWord);
gpo.Save();
}
After that , there are two subkeys created which are:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Group Policy Objects\{27D2FEFF-E5C6-4D8B-B657-0D1E1F2E4BAE}Machine
and
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Group Policy Objects\{27D2FEFF-E5C6-4D8B-B657-0D1E1F2E4BAE}User
and finally the NoDesktop option in Explorer section is created in this address :
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Group Policy Objects\{27D2FEFF-E5C6-4D8B-B657-0D1E1F2E4BAE}User\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer
though still its not working ! Whats wrong ? its driving me insane!
Setting a GPO alone does not make it active. GPOs usually get reapplied at boot or after a certain period of time. You can probably run something like gpupdate /force (as Administrator) to force reapplying GPOs.
Related
I have created an application(windows) compiled with .NET 4.6.1 and used the FolderBrowserDialog object. When a button is pressed I execute this code:
FolderBrowserDialog folderbrowserdialog = new FolderBrowserDialog();
folderbrowserdialog.Description = "Custom Description";
if (folderbrowserdialog.ShowDialog() == DialogResult.OK)
{
filePath = folderbrowserdialog.SelectedPath ;
}
what i get from the folderbrowserdialog(like foto)
however ,the folder browserdialog is not showing the networks shared folder(that the purpose of my app) otherewise just the pc folders.
but what i want to get it is the network shared folders which could i also access from windows 10 like foto here:
notes to be marked:
i could not use the open file dialog cause i need the folder location.
i desgined the Appto be opened just like admin by adding manisfest so the app is always starting like admin.
the app should be comptiable with windows 10,7
note i know that i could try setting this registry option (could be broken in Win10):
HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/Policies/System
EnableLinkedConnections=1
but it does not make a sense to add this registry by every customer PC
so is there any tipps to show the network shared folders in FolderBrowserDialog ?
Finally after reading many topics i found that the only solution is to add a Registry key programmatically so here how to add specfic C# Registry Subkey with dword value:
i wrote a method wich could all use it
just to let you know after using it you have to restart the device after it ,it will work ;)
public void ConfigureWindowsRegistry()
{
RegistryKey localMachine = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64); //here you specify where exactly you want your entry
var reg = localMachine.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", true);
if (reg == null)
{
reg = localMachine.CreateSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", true);
}
if (reg.GetValue("EnableLinkedConnections") == null)
{
reg.SetValue("EnableLinkedConnections", "1", RegistryValueKind.DWord);
MessageBox.Show(
"Your configuration is now created,you have to restart your device to let app work perfektly");
}
}
I had the same issue. The reason of the problem: I was using as an Administrator. The mapped drives are related to the user, so I tried to use as an normal user and I could see the mapped drives.
So, I have a task to:
1. Delete all settings in Internet Connection Properties
2. Set Use Automatic Configuration Script to my script
This is my code, and sometimes it works and values are in IE, and sometimes values are not in IE. I am frustrated with this hectic behavior and wondering where is my error (not in DNA ;))
RegistryKey registry = Registry.CurrentUser.OpenSubKey(
"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
registry.SetValue("ProxyEnable", 0);
registry.Close();
RegistryKey registry2 = Registry.CurrentUser.OpenSubKey(
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Connections", true);
registry2.DeleteValue("DefaultConnectionSettings", false);
registry2.Close();
RegistryKey registry3 = Registry.CurrentUser.OpenSubKey(
#"Software\Microsoft\Windows\CurrentVersion\Internet Settings", true);
registry3.SetValue("AutoConfigURL", #"http://wwwwwwwww/configscript.pac", Microsoft.Win32.RegistryValueKind.String);
registry3.SetValue("ProxyEnable", 000000, RegistryValueKind.DWord);
registry3.Close();
I suspect that the issue you face has something to with stale values on the UI.
The quickest way to check whether your settings are "sticky" is to open Internet options and going to Lan settings directly from control panel.
The following command will launch "internet options"
control inetcpl.cpl
Further if your machine belongs to some corporate domains, there might be group policies set by admins that periodically enforces some values for these parameters.
In such cases, you might have to schedule a task for say every 10 minutes, and enforce values of your choice. (note: that is what I have been doing for quite some time)
How can I get the number of times a program has previously run in c# without keeping a file and tallying. Is there a Application class or something in c# to check the count.
Please give a detailed explantion as i know nothing about it.This is A windows console application not windows forms.
You can do that my creating an Entry in the Registry. And another way is by using an Application Settings.
But I prefer Application Settings because it has less task to do.
See HERE: Creating an Application Settings.
Tutorial From Youtube
Recent versions of Windows automatically maintain this information in the registry under HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist.
The data is obfuscated with ROT13, but that's easy to "decrypt". A free utility (with source code) is available and can serve as your starting point.
You could send a message to a database or webservice every time the program starts up (assuming there's a network connection).
You could keep a count on some form of hardware thet's not a standard storage device (therefore not technically being a file).
You could make a registry entry that you keep the count in (if you ignore the fact that the registry entry is, at some level, persisted into a file somewhere).
You could just have a file somewhere that keeps track of the count. Not sure why you're so opposed to this one in the first place....
If you are running a Winforms application, the you can easily use the Application Settings. Right click on your Solution Name --> Properties --> Settings Tab. More info and tutorial here.
Then, every time your program starts, increment this setting and save it.
Ref: Count the number of times the Program has been launched
In my knowledge Windows does not keep this information for you. You would have to tally the value somewhere (file, database, registry setting).
Better way is Application Settings as:
Create setting in app.config and then use it as:
Properties.Settings.Default.FirstUserSetting = "abc";
then, you usually do this in the Closing event handler of the main form. The following statement to Save settings method.
Properties.Settings.Default.Save();
Implementation using Registry:
static string AppRegyPath = "Software\\Cheeso\\ApplicationName";
static string rvn_Runs = "Runs";
private Microsoft.Win32.RegistryKey _appCuKey;
public Microsoft.Win32.RegistryKey AppCuKey
{
get
{
if (_appCuKey == null)
{
_appCuKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(AppRegyPath, true);
if (_appCuKey == null)
_appCuKey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(AppRegyPath);
}
return _appCuKey;
}
set { _appCuKey = null; }
}
public int UpdateRunCount()
{
int x = (Int32)AppCuKey.GetValue(rvn_Runs, 0);
x++;
AppCuKey.SetValue(rvn_Runs, x);
return x;
}
If it's a WinForms app, you can hook the Form's OnClosing event to run UpdateCount.
Then Check tutorial to Read, write and delete from registry with C#
I have a Problem, which is... i start a programm with right click -> run as administrator.
Which means the programm is running in an administrative context.
WindowsIdentity.GetCurrent().Name;
if i try to get the user name that way i will get the user that started the programm as admin.. for example "administrator", but what i need is the name of the current logged in user which is for example: bob
Can anybody help me out? :)
You could try using WMI (System.Management.dll) to get the owner of the explorer.exe process.
string GetExplorerUser()
{
var query = new ObjectQuery(
"SELECT * FROM Win32_Process WHERE Name = 'explorer.exe'");
var explorerProcesses = new ManagementObjectSearcher(query).Get();
foreach (ManagementObject mo in explorerProcesses)
{
string[] ownerInfo = new string[2];
mo.InvokeMethod("GetOwner", (object[])ownerInfo);
return String.Concat(ownerInfo[1], #"\", ownerInfo[0]);
}
return string.Empty;
}
This relies on the fact that the explorer process is single instance an so you don't end up with the possibility of having several explorer processes running with different user credentials.
You will probably need to use win32 API for that. Read about Window Station and Desktop functions here: http://msdn.microsoft.com/en-us/library/ms687107%28v=vs.85%29.aspx
Also see this question:
Get the logged in Windows user name associated with a desktop
Maybe you could start as normal user, save user name, then programmatically request elevation :
Windows 7 and Vista UAC - Programmatically requesting elevation in C#
All .NET libraries will give you the user from the current context ('Administrator' in your case).
If you are trying to secure your code, you might consider reading about: Security in the .NET framework
1) Cassia should be able to give you a list of currently logged in users including RDC.
foreach (ITerminalServicesSession sess in new TerminalServicesManager().GetSessions())
{
// sess.SessionId
// sess.UserName
}
2) WMI (SO answer)
Select * from Win32_LogonSession
3) PInvoke to WTSEnumerateSessions
4) Enumerate all instances of "explorer.exe" and get the owner using PInvoke (OpenProcessHandle).
Process[] processes = Process.GetProcessesByName("explorer");
This is a bit hacky. WMI can also be used for this.
It might be a good idea to set winmgmt as a dependency for your service if you decided to go with solution that uses WMI.
c# windows forms: How do you create new settings at run time so that they are permanently saved as Settings.Default.-- values?
Just in case that still matters to anyone:
You can dynamically add settings through Settings.Default.Properties.Add(...) and have these also persisted in the local storage after saving (I had those entries reflected in the roaming file).
Nevertheless it seems that the dynamically added settings keep missing in the Settings.Default.Properties collecion after loading again.
I could work around this problem by adding the dynamic property before first accessing it.
Example (notice that I "create" my dynamic setting from a base setting):
// create new setting from a base setting:
var property = new SettingsProperty(Settings.Default.Properties["<baseSetting>"]);
property.Name = "<dynamicSettingName>";
Settings.Default.Properties.Add(property);
// will have the stored value:
var dynamicSetting = Settings.Default["<dynamicSettingName>"];
I don't know if this is supported by Microsoft as the documentation is very rare on this topic.
Problem is also described here http://www.vbdotnetforums.com/vb-net-general-discussion/29805-my-settings-run-time-added-properties-dont-save.html#post88152 with some solution offered here http://msdn.microsoft.com/en-us/library/saa62613(v=VS.100).aspx (see Community Content - headline "How to Create / Save / Load Dynamic (at Runtime) Settings"). But this is VB.NET.
In addition to John's solution for saving, the proper method for loading is add the property, and then do a Reload() on your settings.
Your dynamic setting will be there!
For a full example, valid for using in library code, as you can pass the settings in ..
ApplicationSettingsBase settings = passed_in;
SettingsProvider sp = settings.Providers["LocalFileSettingsProvider"];
SettingsProperty p = new SettingsProperty("your_prop_name");
your_class conf = null;
p.PropertyType = typeof( your_class );
p.Attributes.Add(typeof(UserScopedSettingAttribute),new UserScopedSettingAttribute());
p.Provider = sp;
p.SerializeAs = SettingsSerializeAs.Xml;
SettingsPropertyValue v = new SettingsPropertyValue( p );
settings.Properties.Add( p );
settings.Reload();
conf = (your_class)settings["your_prop_name"];
if( conf == null )
{
settings["your_prop_name"] = conf = new your_class();
settings.Save();
}
Since the Settings class is generated at build time (or, actually, whenever you update the settings file from within the designer), you can't use this mechanism for dynamic scenarios. You can, however, add some collection or dictionary to the application settings and modify that dynamically.
You can't add settings directly (at least not without editing the config XML at runtime), but you can fake it.
In my case, I had a group of identical custom controls on the form, and I wanted to store the runtime state of each control. I needed to store the state of each control, since each one had different data it.
I created a new StringCollection setting named ControlData and placed my own data in there. I then load the data from that list and use it to initialize my controls.
The list looks like this:
Box1Text=A
Box1List=abc;def;foo;bar;
Box2Text=hello
Box2List=server1;server2;
In my startup code, I read through the key/value pairs like this:
foreach (string item in Properties.Settings.Default.ControlData) {
string[] parts=item.split('=');
parts[0] will have the key and parts[1] will have the value. You can now do stuff based on this data.
During the shutdown phase, I do the inverse to write the data back to the list. (Iterate through all the controls in the form and add their settings to ControlData.
How would you access the new settings that you have created? The point of the Visual Studio settings designer is that you can write code that uses these settings with compile-time checking of your code. If you want to dynamically create new settings for your app to use, you will also need to dynamically load them. For dynamic settings, you may want to look at the System.Configuration assembly, notably ConfigurationSection. You can create a custom configuration section with that, which you could use for dynamic setting addition/removal. You might use a ConfigurationCollection for that dynamic addition/removal.
INI files eh? Google turned up this INI library for .NET.
What you could do is create a new registry key.
Name the new key "Your program settings".
RegistryKey ProgSettings = Registry.CurrentUser.OpenSubKey("Software", true);
ProgSettings.CreateSubKey("Your Program settings");
ProgSettings.Close();
Now you can add String Identifiers and values.
RegistryKey ProgSettings = Registry.CurrentUser.OpenSubKey("Software\\Your Program settings", true);
ProgSettings.SetValue("Setting Name", value); // store settings
string settings = ProgSettings.GetValue("Setting Name", false); // retreave settings
ProgSettings.DeleteValue("Setting Name", false);
Besure to close the registry key when you are done to avoid conflicts with other parts of your program that may write to the registry.
Many comercial software applications use these methods.
stackoverflow has many examples about writing and reading to the registry.
This is much easyer then modifying the appconfig.xml file that is used when you create settings.
It took me a long time using the top two answers here plus this link (Create new settings on runtime and read after restart) to get it to finally work.
First of all, set your expectations. The answer here will create a new user setting and you can get its value the next time you launch your app. However, the setting you created this way will not appear in the Settings designer. In fact, when you relaunch the app and try to access the setting in your code, it will not find it. However, the setting you have created through code is saved in the user.config file (say jDoe.config) somewhere in your file system. For you to access this value, you have to add the setting again.
Here is a working example I have:
private void FormPersistence_Load(object sender, EventArgs e)
{
StartPosition = FormStartPosition.Manual;
// Set window location
var exists = Settings.Default.Properties.OfType<SettingsProperty>().Any(p => p.Name == Name + "Location");
if (exists)
{
this.Location = (Point)Settings.Default[Name + "Location"];
}
else
{
var property = new SettingsProperty(Settings.Default.Properties["baseLocation"]);
property.Name = Name + "Location";
Settings.Default.Properties.Add(property);
Settings.Default.Reload();
this.Location = (Point)Settings.Default[Name + "Location"];
}
}
Note:
My new setting's name will be resolved at run time. Name is really this.Name, which is the form's name. This is a base form that other forms can inherit from, so all the child forms will be able to remember their locations.
baseLocation is a setting I have manually created in Settings designer. The new setting I have is the same type. This way I don't have to worry about things like provider, type, etc. in code.
I see how what I wanted was the wrong idea. I'm porting a c++ app over to c# and it has a lot of ini file settings and I was looking for a shortcut to add them in. I'm lazy.