How I can get list COM+ services running on remote servers? and how to set identity to com+ server remotely.
You can use the COM+ Administration API to accomplish this. It allows you to administer services in the local or remote catalog. See this article for guidance on how to get and set properties. Here's a simple example written in C#. You will add a reference to the COM + 1.0 Admin Type Library
using COMAdmin;
COMAdminCatalogCollection applications;
COMAdminCatalog catalog;
catalog = new COMAdminCatalog();
// To connect to a remote server you would user the following
catalog.Connect(serverName);
applications = (COMAdminCatalogCollection)catalog.GetCollection("Applications");
applications.Populate();
foreach (COMAdminCatalogObject application in applications)
{
//do something with the application
if (application.Name.Equals("MyAppName"))
{
application.Value["Identity"] = #"MACHINE\UserName";
application.Value["Password"] = #"UserPassword";
}
}
Related
I am trying to connect to WSUS server remotely from my web application built in ASP.NET Core 2.0. I am using the Microsoft.UpdateServices.Administration.dll to achieve this. I was able to establish successful connection to the server when I built a C# console application and used the same dll file in assembly reference.
I have referred to these similar posts but I have not found an answer yet.
- Is there RESTful webservice calls avaible in WSUS
- How to make a SOAP call to WSUS Server
[I am sorry for not maintaining indentation and proper formatting in the sample code.]
Below is the sample code from the console app which worked:
using System;
using System.Reflection;
using Microsoft.UpdateServices.Administration;
namespace WsusRemoteConnectivityConsoleApp
{
class Program
{
static void Main(string[] args)
{
IUpdateServer remoteServer =
AdminProxy.GetUpdateServer("WsusServer1",false,8530);
Console.WriteLine(remoteServer.Name);
}
}
}
The expected output as well as the actual output in the console app is "WsusServer1".
But using the same line of code in the web app, I am not able to connect to the WSUS server. I receive exception saying that "The requested security protocol is not supported" in this line
IUpdateServer remoteServer =
AdminProxy.GetUpdateServer("WsusServer1",false,8530);
Any help is appreciated.
Thanks.
if you have setup SSL, you should use:
AdminProxy.GetUpdateServer("WsusServer1",true,8531);
We are running TFS and Release Management on premises, and i want to deploy my applications to a remote datacenter.
Access is over the internet, so there is no windows shares available.
I am using the vNext templates, and afaik RM seems to only support unc paths over windows shares.
How can i use Release Management to deploy software to this datacenter?
Im working on this solution:
Use WebDav on a IIS located inside the datacenter.
RM server and Target can use the WebDav client built into windows and access it by an unc path.
I haven't gotten this to work yet, as RM won't use the correct credentials to logon to the webdav server.
Updated with my solution
This is only a proof of concept, and is not production tested.
Setup a WebDav site accessible from both RM server and Target server
Install the feature "Desktop experience" on both servers
Make the following DLL
using System;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.IO;
using Microsoft.TeamFoundation.Release.Common.Helpers;
using Microsoft.TeamFoundation.Release.Composition.Definitions;
using Microsoft.TeamFoundation.Release.Composition.Services;
namespace DoTheNetUse
{
[PartCreationPolicy(CreationPolicy.Shared)]
[Export(typeof(IThreadSafeService))]
public class DoTheNetUse : BaseThreadSafeService
{
public DoTheNetUse() : base("DoTheNetUse")
{}
protected override void DoAction()
{
Logger.WriteInformation("DoAction: [DoTheNetUse]");
try
{
Logger.WriteInformation("# DoTheNetUse.Start #");
Logger.WriteInformation("{0}, {1}", Environment.UserDomainName, Environment.UserName);
{
Logger.WriteInformation("Net use std");
var si = new ProcessStartInfo("cmd.exe", #"/c ""net use \\sharedwebdavserver.somewhere\DavWWWRoot\ /user:webdavuser webdavuserpassword""");
si.UseShellExecute = false;
si.RedirectStandardOutput = true;
si.RedirectStandardError = true;
var p = Process.Start(si);
p.WaitForExit();
Logger.WriteInformation("Net use output std:" + p.StandardOutput.ReadToEnd());
Logger.WriteInformation("Net use output err:" + p.StandardError.ReadToEnd());
}
//##########################################################
Logger.WriteInformation("# Done #");
}
catch (Exception e)
{
Logger.WriteError(e);
}
}
}
}
Name it "ReleaseManagementMonitor2.dll"
Place it in the a subfolder to The service "ReleaseManagementMonitor"
Configure the shared path as the solution below states.
DO NOT OVERWITE THE EXISTING "ReleaseManagementMonitor2.dll"
The reason that this works is MEF.
The ReleaseManagementMonitor service tries to load the dll "ReleaseManagementMonitor2.dll" from all subfolders.
This dll implements a service interface that RM recognises.
It the runs "net use" to apply the credentials to the session that the service runs under, and thereby grants access to the otherwise inaccessible webdav server.
This solution is certified "Works on my machine"
RM does work only with UNC, you are right on that.
You can leverage that to make your scenario work -
In Theory
Create a boundary machine on the RM domain, where your drops can be copied.
The deploy action running on your datacenter can then copy bits from this boundary machine, using credentials that have access on that domain. (These credentials are provided by you in the WPF console)
How this works
1. Have a dedicated machine on the RM server domain (say D1) that will be used as a boundary machine.
2. Define this machine as a boundary machine in RM by specifying a shared path that will be used by your data centre. Go to settings tab in your WPF console, create a new variable - { Key = RMSharedUNCPath, Value = \\BoundaryMachine\DropsLocation }. RM now understands you want to use this machine as your boundary machine.
3. Make sure you take care of these permissions
RM Server should have write permissions on the \\BoundaryMachine\DropsLocation share.
Pass down credentials of domain D1 to the target machine in the data centre (Domain D2), that can be used to access the share.
4. Credentials can be passed down fron the WPF console, you will have to define the following two config variables in the settings tab again.
Key = RMSharedUNCPathUser ; Value = domain D1 user name
Key = RMSharedUNCPathPwd ; Value = password for the user defined above.
PS - Variable names are case sensitive.
Also, to let RM know that you want to use the SharedUNC mechanism, check the corresponding checkbox for the RM server and connect to it via IP and not DNS name as these must be in different domains, i.e.
Try to use Get-Content on local-server then Set-Content on the remote server passing the file contents over;
Could package everything into an archive of some kind.
The Release Management is copying VisualStudioRemoteDeployer.exe to C:\Windows\DtlDownloads\VisualStudioRemoteDeployer folder on the target server then is copying the scripts from the specified location to target server using robocopy.
So you have to give permissions from your target server to your scripts location.
Release Management update 4 supports "Build drops stored on TFS servers"
http://blogs.msdn.com/b/visualstudioalm/archive/2014/11/11/what-s-new-in-release-management-for-vs-2013-update-4.aspx
I have a windows service "Service1" configured to log on as "Local Service".
I built a console application to start it programmatically.
var service = new ServiceController("Service1");
service.Start();
I know that if I run the ConsoleApplication1 from an administrator command prompt it starts smoothly.
And if I run it without elevation I get an:
System error 5 has occurred.
Access is denied.
But, I need to start it without elevation.
Is it possible, or I have to change the way to achieve this?
You can set the ACL for the service itself to allow this. The SetACL.exe utility makes this (somewhat) straightforward; e.g.:
SetACL.exe -on "MyService" -ot srv -actn ace -ace "n:S-1-5-32-545;p:start_stop"
This allows members of the Users group (S-1-5-32-545) to start and stop MyService.
I followed torak link and I understand this key difference concerning rights in a service:
a service has rights concerning the "Run as" user
a service has different permission to control the service (i.e. to start/stop it)
So, to start the service I need to modify the service control permission.
Well, I have done a windows service called Service1 and I made an installer with WIX.
During setup I call ServiceInstall
<ServiceInstall Id="ServiceInstaller" Type="ownProcess" Vital="yes"
Name="Service1" DisplayName="Service1"
Description="Service1 description"Start="demand"
Account="NT AUTHORITY\LocalService"
ErrorControl="ignore" Interactive="no" >
</ServiceInstall>
Then I have a client program called TestProgram where I try to start the service:
var service = new ServiceController("Service1");
service.Start();
And obviously it doesn't start the service without elevation of TestProgram (that runs under a normal user account).
So the solution is to instruct WIX to allow members of the user group (for example) to start/stop the service, using the PermissionEx tag:
<util:PermissionEx User="Users" ServiceStart="yes" ServiceStop="yes">
</util:PermissionEx>
Hope this helps. Thank you all.
If i can add my 2 cents, here is my solution that wont require any complex App.Manifest or Windows Service modification.
The concept is simply to call "Net Start" through a process that is elevated :
public string StartServiceViaProcess(string param_strServiceName)
{
try
{
const int ERROR_CANCELLED = 1223; //The operation was canceled by the user.
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Verb = "runas";
startInfo.UseShellExecute = true;
startInfo.Arguments = "/C net start " + param_strServiceName;
process.StartInfo = startInfo;
try
{
Process.Start(startInfo);
}
catch (Win32Exception ex)
{
if (ex.NativeErrorCode == ERROR_CANCELLED)
return "L'usager a annulé la demande d'exécution avec privilège.";
else
throw;
}
}
catch (Exception ex)
{
return ex.SI_ConvertToString();
}
return "";
}
I don't think you can do it - It is my understanding that this is due to security reasons. Allowing malware to automatically elevate itself would be problematic.
This is the link that I followed and solved my issue.
How to Grant non-Administrators Rights to Manage Services
By default, common users with no system administrator privileges
cannot manage Windows services. It means that they cannot stop, start
or change the settings or permissions for such services. In some
cases, it is necessary that a user had the permissions to restart or
manage certain services. In this article, we’ll consider some ways to
manage permissions for Windows services. In particular, we’ll show how
to grant a standard user without administrative rights the permissions
to start and stop a specific service...
There is no simple and convenient integrated tool to manage services
permissions in Windows. We’ll consider some ways to grant a user
permissions to manage service...
I have a web app that I've created using Entity Framework Code First. In setting it up I have managed to match my DB connection string to my DBContext by specifying the full namespace and class of the DBContext as the name of the connection string.
<add name="MyClassProject.EfDbContext" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=MyDatabase;Integrated Security=true;User Id=MyUsername;Password=MyPassword;" providerName="System.Data.SqlClient"/>
Initially when I set up the project, I just had it created in c:\inetpub\wwwroot, and just ran it through Visual Studio. Everything worked fine.
Now I'm trying to have the code build to a separate website folder, and have the website run as it's own website and app pool in IIS. I've set up the website, and my hosts file but when I went to run it I received the following error.
Cannot open database "MyDatabase" requested by the login. The login failed.
Login failed for user 'IIS APPPOOL\MyAppPool'.
I'm wondering why this is happening, as I seem to be specifying the security username and password to use for the DB in my connection string....so why is it trying to connect as the app pool that my website is running in?
Also, how can I fix this, without having to give MyAppPool (or Network Service if I changed it to that) DB permissions in SQL Server?
Update: I should've mentioned that I initialise my DBContext class using:
namespace MyClassProject
{
public class EfDbContext : DbContext
{
public EfDbContext() : base ("MyDatabase")
{
}
}
}
I found the issue.
When I initialise my DBContext class with : base("MyDatabase"), it overrides the connection string specified in the web.config.
Removing that from my DBContext class, with the database already existing, the site now works in IIS.
However, if I don't have the database created already, (or if I have my database initialiser use DropCreateDatabaseWhenModelChanges or DropCreateDatabaseAlways so that it'll needs to recreate the DB), the initialiser will fail, as it'll try to use an SQL user that doesn't have permissions to create the DB.
My way around it is to use the : base("MyDatabase") and run from Visual Studio initially so the database is created.
Then remove it from code, add the specified user to the DB security in SQL Server, and it'll allow my site to run in IIS thereafter.
Remove Integrated Security=true;. That is the setting that passes the current user off.
When using Integrated Security, the DB is given a token from the user who is currently running the process. In all likelihood, you run Visual Studio from your user account, which likely has Admin permissions on your SQL Server instance.
When IIS runs your app, it uses something called an Application Pool (or App pool). You can have multiple apps in a single pool to be managed together. The app pool also runs under a special user account named for the pool. App pool users exist under a container called "IIS AppPool", so the local user for the DefaultAppPool is IIS AppPool\DefaultAppPool. If you want to grant access to a resource on your local system (including file permissions), you can also grant it to the app pool user or local group IIS_IUSRS to grant it to all app pools.
Remember that these are local accounts, so they will not cross network boundaries. To grant permissions on a different server, you'll need to either use a domain user (or even better, a domain Managed Service Account) or you can set the app pool user to NETWORK SERVICE and then you can grant permissions to MyDomain\MyWebServer$ (the dollar sign is important).
You can use Web.config Transform to have Local connection stirng different from Remote (say in Release mode). To start using it you need to publish your Web App using One-Click Publish from Visual Studio. That's really very handy way to publish web apps!
Looks like that's what you're looking for.
Or set connection string name base on a condition:
public EfDbContext() : base (GetConnectionStringName())
{
}
private static GetConnectionStringName()
{
return RunLocally() : "LocalDatabase" : "RemoteDatabase";
}
private static bool RunLocally()
{
// implement some how
}
I need to deploy my COM dll as a COM+ application. I used to do that from Component Services manager (dcomcnfg.exe). But my requirement is to deploy it from command-line. Is there a command to do that?
Update: And how to uninstall the same?
Thanks.
Here are a couple of scripts that dump a COM+ application's settings to an XML file, as well as installs applications from and XML file. It provided me a good framework for doing something similar a while back. It contains example code of how to create and remove COM+ applications using the COM+ administration API.
This vbscript snippet creates an application and installs a component:
Dim catalog
Dim applications
Dim application
Set catalog = CreateObject("COMAdmin.COMAdminCatalog")
Set applications = catalog.GetCollection("Applications")
Call applications.Populate
Set application = applications.Add()
' ID is an arbitrary GUID, that you can create using uuidgen
application.Value("ID") = "{da2d72e3-f402-4f98-a415-66d21dafc0a9}"
application.Value("Name") = "SampleApp"
application.Value("Activation") = 0' COMAdmin.COMAdminActivationOptions.COMAdminActivationLocal
application.Value("ApplicationAccessChecksEnabled") = 0 'COMAdmin.COMAdminAccessChecksLevelOptions.COMAdminAccessChecksApplicationComponentLevel
application.Value("Description") = "Sample Application"
'application.Value("Identity") = "machine\administrator"
'application.Value("Password") = "YourPassword"
application.Value("RunForever") = True
Call applications.SaveChanges
catalog.InstallComponent "SampleApp", "C:\Documents and Settings\me\My Documents\Test\MyTestProj.dll", "", ""
Set application = Nothing
Set applications = Nothing
Set catalog = Nothing
This is running on Windows XP -- other OS's may have different behavior. And it does seem to be pretty temperamental. If it doesn't work the errors are really vague and unhelpful.
To delete I think you will have to iterate over the the components in the application and remove from the list as per this example. I think a similar approach would be required to remove the entire application.
References
See Configurating COM+ for a good easy to understand article (but is not in script). MSDN has a good reference on Automating COM+ Administration and also the complete COM+ Administration Reference.