How do I install a C# Windows service without creating an installer? - c#

Does anyone know if there is a way to install a Windows service created in C# without making an installer?

I include a class that does the installation for me. I call the application using command line parameters to install or uninstall the app. I have also in the past included a prompt to the user whether they wanted the service installed when started directly from the command line.
Here's the class I use:
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using Microsoft.Win32;
namespace [your namespace here]
{
class IntegratedServiceInstaller
{
public void Install(String ServiceName, String DisplayName, String Description,
System.ServiceProcess.ServiceAccount Account,
System.ServiceProcess.ServiceStartMode StartMode)
{
System.ServiceProcess.ServiceProcessInstaller ProcessInstaller = new System.ServiceProcess.ServiceProcessInstaller();
ProcessInstaller.Account = Account;
System.ServiceProcess.ServiceInstaller SINST = new System.ServiceProcess.ServiceInstaller();
System.Configuration.Install.InstallContext Context = new System.Configuration.Install.InstallContext();
string processPath = Process.GetCurrentProcess().MainModule.FileName;
if (processPath != null && processPath.Length > 0)
{
System.IO.FileInfo fi = new System.IO.FileInfo(processPath);
//Context = new System.Configuration.Install.InstallContext();
//Context.Parameters.Add("assemblyPath", fi.FullName);
//Context.Parameters.Add("startParameters", "Test");
String path = String.Format("/assemblypath={0}", fi.FullName);
String[] cmdline = { path };
Context = new System.Configuration.Install.InstallContext("", cmdline);
}
SINST.Context = Context;
SINST.DisplayName = DisplayName;
SINST.Description = Description;
SINST.ServiceName = ServiceName;
SINST.StartType = StartMode;
SINST.Parent = ProcessInstaller;
// http://bytes.com/forum/thread527221.html
// SINST.ServicesDependedOn = new String[] {};
System.Collections.Specialized.ListDictionary state = new System.Collections.Specialized.ListDictionary();
SINST.Install(state);
// http://www.dotnet247.com/247reference/msgs/43/219565.aspx
using (RegistryKey oKey = Registry.LocalMachine.OpenSubKey(String.Format(#"SYSTEM\CurrentControlSet\Services\{0}", SINST.ServiceName), true))
{
try
{
Object sValue = oKey.GetValue("ImagePath");
oKey.SetValue("ImagePath", sValue);
}
catch (Exception Ex)
{
// System.Console.WriteLine(Ex.Message);
}
}
}
public void Uninstall(String ServiceName)
{
System.ServiceProcess.ServiceInstaller SINST = new System.ServiceProcess.ServiceInstaller();
System.Configuration.Install.InstallContext Context = new System.Configuration.Install.InstallContext("c:\\install.log", null);
SINST.Context = Context;
SINST.ServiceName = ServiceName;
SINST.Uninstall(null);
}
}
}
And here's how I call it:
const string serviceName = "service_name";
const string serviceTitle = "Service Title For Services Control Panel Applet";
const string serviceDescription = "A longer description of what the service does. This is used by the services control panel applet";
// Install
IntegratedServiceInstaller Inst = new IntegratedServiceInstaller();
Inst.Install(serviceName, serviceTitle, serviceDescription,
// System.ServiceProcess.ServiceAccount.LocalService, // this is more secure, but only available in XP and above and WS-2003 and above
System.ServiceProcess.ServiceAccount.LocalSystem, // this is required for WS-2000
System.ServiceProcess.ServiceStartMode.Automatic);
// Uninstall
IntegratedServiceInstaller Inst = new IntegratedServiceInstaller();
Inst.Uninstall(serviceName);

You could try the windows sc command
C:\WINDOWS\system32>sc create
DESCRIPTION:
SC is a command line program used for communicating with the NT Service Controller and services.

You can use installutil.
From the command line:
installutil YourWinService.exe
This utility is installed with the .NET Framework

Related

Is it possible to get a batch of text content through Azure DevOps REST API?

I need to get (not download) the content from 10.000~ manifest files within a project in Azure DevOps, but I don't manage to achieve this. I have found several ways to retrieve the content from one file at a time, but in this context, it is neither an efficient nor sustainable solution. I have managed to retrieve all files of a particular file type by checking if the file path ends with the name of the file, then using the TfvcHttpClientBase.GetItemsBatch method. However, this method does not return the item's content.
Program.cs
using Microsoft.TeamFoundation.SourceControl.WebApi;
AzureRest azureRest = new AzureRest();
var tfvcItems = azureRest.GetTfvcItems();
List<TfvcItemDescriptor> itemDescriptorsList = new List<TfvcItemDescriptor>();
foreach(var item in tfvcItems)
{
//Example manifest file .NET
if (item.Path.EndsWith("packages.config"))
{
var itemDescriptor = new TfvcItemDescriptor()
{
Path = item.Path,
RecursionLevel = VersionControlRecursionType.None,
Version = "",
VersionOption = TfvcVersionOption.None,
VersionType = TfvcVersionType.Latest
};
itemDescriptorsList.Add(itemDescriptor);
}
}
TfvcItemDescriptor[] itemDescriptorsArray = itemDescriptorsList.ToArray();
var itemBatch = azureRest.GetTfvcItemsBatch(itemDescriptorsArray);
foreach(var itemList in itemBatch)
{
foreach(var itemListList in itemList)
{
Console.WriteLine("Content: " + itemListList.Content); //empty/null
Console.WriteLine("ContentMetadata: " + itemListList.ContentMetadata); //not empty/null
}
}
AzureRest.cs
using Microsoft.TeamFoundation.SourceControl.WebApi;
using Microsoft.VisualStudio.Services.Common;
using Microsoft.VisualStudio.Services.WebApi;
public class AzureRest
{
const string ORG_URL = "https://org/url/url";
const string PROJECT = "Project";
const string PAT = "PersonalAccessToken";
private string GetTokenConfig()
{
return PAT;
}
private string GetProjectNameConfig()
{
return PROJECT;
}
private VssConnection Authenticate()
{
string token = GetTokenConfig();
string projectName = GetProjectNameConfig();
var credentials = new VssBasicCredential(string.Empty, token);
var connection = new VssConnection(new Uri(ORG_URL), credentials);
return connection;
}
public List<TfvcItem> GetTfvcItems()
{
var connection = Authenticate();
using (TfvcHttpClient tfvcClient = connection.GetClient<TfvcHttpClient>())
{
var tfvcItems = tfvcClient.GetItemsAsync(scopePath: "/Path", recursionLevel: VersionControlRecursionType.Full, true).Result;
return tfvcItems;
}
}
public List<List<TfvcItem>> GetTfvcItemsBatch(TfvcItemDescriptor[] itemDescriptors)
{
TfvcItemRequestData requestData = new TfvcItemRequestData()
{
IncludeContentMetadata = true,
IncludeLinks = true,
ItemDescriptors = itemDescriptors
};
var connection = Authenticate();
using (TfvcHttpClient tfvcClient = connection.GetClient<TfvcHttpClient>())
{
var tfvcItems = tfvcClient.GetItemsBatchAsync(requestData).Result;
return tfvcItems;
}
}
}
}
For reference:
I have tested the codes you shared and when debugging at "itemDescriptorsList" and have found that there is no content specified in it, so that's why you cannot get the txt content.
You should first check and add the content property into the "itemDescriptorsList".

Starting two windows services in the same application

I have the following issue.
I have two windows services application to start in the same application (WPF), both were already installed. but when I have to "Start" them (ServiceController.Start()), only the service which starts first keeps turned on, the other returns the message:
Error 1053: The service did not respond to the start or control
request in a timely fashion
This is my code to start them:
//*TS_TimeOut timespan has 1 hour
private void InitServiceOne()
{
ServiceController SControllerServiceOne = new ServiceController("ServiceOne", Environment.MachineName);
SControllerServiceOne.Start();
SControllerServiceOne.WaitForStatus(ServiceControllerStatus.Running, TS_TimeOut);
}
private void InitServiceTwo()
{
ServiceController SControllerServiceTwo = new ServiceController("ServiceTwo", Environment.MachineName);
SControllerServiceTwo.Start();
SControllerServiceTwo.WaitForStatus(ServiceControllerStatus.Running, TS_TimeOut);
}
This is the code that I've used to install them:
private void InstallServiceOne(string strServiceOnePath)
{
ServiceProcessInstaller ProcessServiceServiceOne = new ServiceProcessInstaller();
ServiceInstaller ServiceInstallerOne = new ServiceInstaller();
InstallContext Context = new System.Configuration.Install.InstallContext();
String path = String.Format("/assemblypath={0}", strServiceOnePath));
String[] cmdline = { path };
Context = new System.Configuration.Install.InstallContext("", cmdline);
ServiceInstallerOne.Context = Context;
ServiceInstallerOne.DisplayName = "ServiceOne";
ServiceInstallerOne.Description = "ServiceOne";
ServiceInstallerOne.ServiceName = "ServiceOne";
ServiceInstallerOne.StartType = ServiceStartMode.Automatic;
ServiceInstallerOne.Parent = ProcessServiceServiceOne;
System.Collections.Specialized.ListDictionary stateServiceOne = new System.Collections.Specialized.ListDictionary();
ServiceInstallerObjIntegracao.Install(stateServiceOne);
}
private void InstallServiceTwo(string strServiceTwoPath)
{
ServiceProcessInstaller ProcessServiceServiceTwo new ServiceProcessInstaller();
ServiceInstaller ServiceInstallerTwo = new ServiceInstaller();
InstallContext Context = new System.Configuration.Install.InstallContext();
String path = String.Format("/assemblypath={0}", strServiceTwoPath);
String[] cmdline = { path };
Context = new System.Configuration.Install.InstallContext("", cmdline);
ServiceInstallerTwo.Context = Context;
ServiceInstallerTwo.DisplayName = "ServiceTwo";
ServiceInstallerTwo.Description = "ServiceTwo";
ServiceInstallerTwo.ServiceName = "ServiceTwo";
ServiceInstallerTwo.StartType = ServiceStartMode.Automatic;
ServiceInstallerTwo.Parent = ProcessServiceServiceTwo;
System.Collections.Specialized.ListDictionary stateServiceTwo = new System.Collections.Specialized.ListDictionary();
ServiceInstallerObjBRMonitoring.Install(stateServiceTwo);
}
It's my first question in the stackoverflow community and english is not my mother tongue.
My apologies if I commited any mistake.
The problem have been solved!
I just had to change from Debug to Release and Install the Release .exe, now both services are running and working without any problem.

Creating a instance, virtual on HP cloud or any Openstack Cloud using c#

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;
}

System.ServiceModel.Channels.MessageHeader Error

I'm trying to get the following to work on my machine but I get an error (Cannot create an instance of the abstract class or interface 'System.ServiceModel.Channels.MessageHeader')
using System;
using System.IO;
using System.Reflection;
namespace com.companyname.business
{
/// <summary>
/// Summary description for SessionCreateRQClient.
/// </summary>
class SessionCreateRQClient
{
/// <summary>
/// The main entry point.
/// </summary>
[STAThread]
static void Main(string[] args)
{
try
{
// Set user information, including security credentials and the IPCC.
string username = "user";
string password = "password";
string ipcc = "IPCC";
string domain = "DEFAULT";
string temp = Environment.GetEnvironmentVariable("tmp"); // Get temp directory
string PropsFileName = temp + "/session.properties"; // Define dir and file name
DateTime dt = DateTime.UtcNow;
string tstamp = dt.ToString("s") + "Z";
//Create the message header and provide the conversation ID.
MessageHeader msgHeader = new MessageHeader();
msgHeader.ConversationId = "TestSession"; // Set the ConversationId
From from = new From();
PartyId fromPartyId = new PartyId();
PartyId[] fromPartyIdArr = new PartyId[1];
fromPartyId.Value = "WebServiceClient";
fromPartyIdArr[0] = fromPartyId;
from.PartyId = fromPartyIdArr;
msgHeader.From = from;
To to = new To();
PartyId toPartyId = new PartyId();
PartyId[] toPartyIdArr = new PartyId[1];
toPartyId.Value = "WebServiceSupplier";
toPartyIdArr[0] = toPartyId;
to.PartyId = toPartyIdArr;
msgHeader.To = to;
//Add the value for eb:CPAId, which is the IPCC.
//Add the value for the action code of this Web service, SessionCreateRQ.
msgHeader.CPAId = ipcc;
msgHeader.Action = "SessionCreateRQ";
Service service = new Service();
service.Value = "SessionCreate";
msgHeader.Service = service;
MessageData msgData = new MessageData();
msgData.MessageId = "mid:20001209-133003-2333#clientofsabre.com1";
msgData.Timestamp = tstamp;
msgHeader.MessageData = msgData;
Security security = new Security();
SecurityUsernameToken securityUserToken = new SecurityUsernameToken();
securityUserToken.Username = username;
securityUserToken.Password = password;
securityUserToken.Organization = ipcc;
securityUserToken.Domain = domain;
security.UsernameToken = securityUserToken;
SessionCreateRQ req = new SessionCreateRQ();
SessionCreateRQPOS pos = new SessionCreateRQPOS();
SessionCreateRQPOSSource source = new SessionCreateRQPOSSource();
source.PseudoCityCode = ipcc;
pos.Source = source;
req.POS = pos;
SessionCreateRQService serviceObj = new SessionCreateRQService();
serviceObj.MessageHeaderValue = msgHeader;
serviceObj.SecurityValue = security;
SessionCreateRS resp = serviceObj.SessionCreateRQ(req); // Send the request
if (resp.Errors != null && resp.Errors.Error != null)
{
Console.WriteLine("Error : " + resp.Errors.Error.ErrorInfo.Message);
}
else
{
msgHeader = serviceObj.MessageHeaderValue;
security = serviceObj.SecurityValue;
Console.WriteLine("**********************************************");
Console.WriteLine("Response of SessionCreateRQ service");
Console.WriteLine("BinarySecurityToken returned : " + security.BinarySecurityToken);
Console.WriteLine("**********************************************");
string ConvIdLine = "convid="+msgHeader.ConversationId; // ConversationId to a string
string TokenLine = "securitytoken="+security.BinarySecurityToken; // BinarySecurityToken to a string
string ipccLine = "ipcc="+ipcc; // IPCC to a string
File.Delete(PropsFileName); // Clean up
TextWriter tw = new StreamWriter(PropsFileName); // Create & open the file
tw.WriteLine(DateTime.Now); // Write the date for reference
tw.WriteLine(TokenLine); // Write the BinarySecurityToken
tw.WriteLine(ConvIdLine); // Write the ConversationId
tw.WriteLine(ipccLine); // Write the IPCC
tw.Close();
//Console.Read();
}
}
catch(Exception e)
{
Console.WriteLine("Exception Message : " + e.Message );
Console.WriteLine("Exception Stack Trace : " + e.StackTrace);
Console.Read();
}
}
}
}
I have added the reference System.ServiceModel and the lines:
using System.ServiceModel;
using System.ServiceModel.Channels;
but I continue to get that error when trying to compile --
Cannot create an instance of the abstract class or interface 'System.ServiceModel.Channels.MessageHeader'
I am using Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
Professional Edition
Is there another reference I have to add? Or a dll to move over?
I wonder was the code above written for Framework 2.0 only?
Thanks for your help.
The error message is correct, you cannot create an instance of that class, it is declared abstract.
http://msdn.microsoft.com/en-us/library/system.servicemodel.channels.messageheader.aspx
See if the static method MessageHeader.CreateHeader will work for you. Note there is several overloads, so pick the best one for you.

Modify the code to perform operation on remote servers

I wrote the following code to change the user account and password associated with a Windows Service. How can I modify this code to be able to perform the same operation on a remote system?
static void Main(string[] args)
{
string serviceName = "DummyService";
string username = ".\\Service_Test2";
string password = "Password1";
ServiceController sc = new ServiceController(serviceName);
Console.WriteLine(sc.Status.ToString());
if (sc.Status == ServiceControllerStatus.Running)
{
sc.Stop();
}
Thread.Sleep(2000);
sc.Refresh();
Console.WriteLine(sc.Status.ToString());
string objPath = string.Format("Win32_Service.Name='{0}'", serviceName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
{
object[] wmiParams = new object[11];
wmiParams[6] = username;
wmiParams[7] = password;
service.InvokeMethod("Change", wmiParams);
}
Thread.Sleep(2000);
Console.WriteLine(sc.Status.ToString());
if (sc.Status == ServiceControllerStatus.Stopped)
{
sc.Start();
}
Thread.Sleep(2000);
sc.Refresh();
Console.WriteLine(sc.Status.ToString());
}
Use ServiceController constructor overload that allows target machine-name to be specified
Modify WMI object path to include the target server.
new ManagementPath(
"\\\\ComputerName\\root" +
"\\cimv2:Win32_Service.Name='{0}'");
Make sure your user/password have sufficient rights on target machine, change those if not.

Categories

Resources