Probing Load Exception While Installing Windows Service On .NET - c#

I have a windows service that is written in .NET, and i used probing feature in order to load dll's to this windows service. However, when i open command prompt and try to install windows service using installutil.exe, i got an error such as: "System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
Aborting installation for",
On the other hand, when i move dll's in the same folder with windows service and repeat the installation procedure, windows service is installed successfully.
Do you have any ideas or suggestions about this problem?, is there a probing problem in windows service installation of .NET?

I face the same problem in my project, in my windows service project i have the following app.config section:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="SDK" />
</assemblyBinding>
</runtime>
if i executed the service as a console all is well, but when i try to install it the installutil failed and i got the same exception, so my solution is made the service installed itself by a command line: like so:
cmd: hotspotcenter -i <service_name="service name">
// service_name i made it optional
the Installer class helper:
internal static class BasicServiceInstaller
{
public static void Install(string serviceName)
{
CreateInstaller(serviceName).Install(new Hashtable());
}
public static void Uninstall(string serviceName)
{
CreateInstaller(serviceName).Uninstall(null);
}
private static Installer CreateInstaller(string serviceName)
{
var installer = new TransactedInstaller();
installer.Installers.Add(new ServiceInstaller
{
ServiceName = serviceName,
DisplayName = serviceName,
StartType = ServiceStartMode.Manual
});
installer.Installers.Add(new ServiceProcessInstaller
{
Account = ServiceAccount.LocalSystem
});
var installContext = new InstallContext(
serviceName + ".install.log", null);
installContext.Parameters["assemblypath"] =
Assembly.GetEntryAssembly().Location;
installer.Context = installContext;
return installer;
}
}
in the main entry of the service project:
if (Environment.UserInteractive)
{
bool install = false;
bool uninstall = false;
string serviceName = "YourDefaultServiceName";
var p = new OptionSet()
.Add<bool>("i|install", "Install Windows Service", i => install = i)
.Add<bool>("i|install=", "Install Windows Service", i => install = i)
.Add<bool>("u|uninstall", "Uninstall Window Service", u => uninstall = u)
.Add<string>("sn|service_name=", "Service Name", n => serviceName = n);
p.Parse(args);
if (install)
{
BasicServiceInstaller.Install(serviceName);
return;
}
else if (uninstall)
{
BasicServiceInstaller.Uninstall(serviceName);
return;
}
// if no install or uninstall commands so start the service as a console.
var host = new YourService();
host.Start(args);
Console.ReadKey();
}
else
{
ServiceBase.Run(new HotspotCenterService());
}

Without exact information, I would suggest following:
check the exception details to see what exactly went wrong
use Fusion Log Viewer, to see which assemblies failed binding
check whether your probing configuration matches your deployment
Probing is configured as described here.

Related

SharePoint Foundation 2013 Event Receiver never fires

I'm attempting to add custom event listeners to my Sharepoint Foundation 2013 server, however even though I seem to be able to register them, I can't get them to fire when the event is happening, eg. updating an item in the list.
I'm using a console application to add & install the library that has the overridden functions.
FeatureInstaller (Console app):
static void Main(string[] args)
{
string assemblyName = typeof(Feature.TestFeature).Assembly.FullName;
string className = "Feature.TestFeature";
SPSite spSite = new SPSite(#"http://URLToServer/");
SPWeb spWeb = spSite.OpenWeb();
SPList spList = spWeb.Lists["Items"];
//Remove old event listener
for (int i = 0; i < spList.EventReceivers.Count; i++)
if (spList.EventReceivers[i].Type == SPEventReceiverType.ItemUpdating)
spList.EventReceivers[i--].Delete();
//Add new event listener
spList.EventReceivers.Add(SPEventReceiverType.ItemUpdating, assemblyName, className);
spWeb.Close();
spSite.Close();
Console.WriteLine("Done");
Console.ReadLine();
}
Feature (Library):
Namespace: Feature
public class TestFeature : SPItemEventReceiver
{
public void SendToEventLog(string message)
{
using (EventLog eventLog = new EventLog("Application"))
{
eventLog.Source = "Application";
eventLog.WriteEntry(message, EventLogEntryType.Information);
}
}
public override void ItemUpdating(SPItemEventProperties properties)
{
SendToEventLog("Hello World!");
base.ItemUpdating(properties);
}
}
What I have done prior to building the solution:
Added Microsoft.SharePoint.dll to both projects' references
Added Feature project as reference to FeatureInstaller
Signed Feature using a generated key without password protection
"Make assembly COM-Visible" set to true for Feature in Assembly Information
Added [assembly: AssemblyKeyFile("absolutePathToKeyFileInSolution")] line to AssemblyInfo.cs for Feature
Steps:
After copying the console app's executable as well as the Feature.dll to my server;
gacutil -i Feature.dll
The library appeared in the C:\Windows\Microsoft.NET\assembly\GAC_MSIL directory
I launched the console app, which ran without any errors, adding my custom event listener (I later verified this by listing all the event listeners by assembly & classname)
iisreset
After restarting, I went to the list, updated an item's title, but no event log was created & I recieved no errors either.
What did I overlook?

xsd to class (C#) in visual studio 2019

I am following a tutorial, in one step it opens "VS2012 arm cross tools command prompt" and executes
xsd file.xsd /classes
I can't find "VS2012 arm cross tools command prompt" on my computer (my guess it's because I'm using VS2019) so I open the "Developer command prompt for VS 2019" instead, but when I run the command, I get an error:
"xsd" is not recognized as an internal or external command, program or executable batch file
Can someone tell me how I can create a class from an xsd file in VS 2019? Thank you for your time.
Once you have installed the Windows SDK. The following could be of help to you...it is .NET Core. Browse to the xsd.exe and add a reference to it in VS 2019.
class Program
{
static void Main(string[] args)
{
var rgs = new string[]
{
#"PathToYourDLL\My.dll",
"/type:ClassNameToGen"
};
AppDomain.CurrentDomain.FirstChanceException += (s, e) =>
{
string error = e.Exception.ToString();
var typeLoadException = e.Exception as ReflectionTypeLoadException;
if (typeLoadException != null)
{
foreach (var exception in typeLoadException.LoaderExceptions)
{
error += Environment.NewLine + Environment.NewLine + exception.ToString();
}
}
Console.WriteLine(error);
};
XsdTool.Xsd.Main(rgs);
Console.ReadLine();
}
}

Running SSIS Package in C# Error

I get this error message when trying to run a SSIS package in C#. The error is:
Error in Microsoft.SqlServer.Dts.Runtime.TaskHost/SSIS.Pipeline : To run a SSIS
package outside of SQL Server Data Tools you must install Standard Edition of Integration Services or higher.
I checked the development machine and the server, and both have the SSDT installed. The target SQL Server is 2012, and I ran a report to check the edition of Integration Services that is running and it is the Standard Edition (11.3.6020.0). I noticed that the error occurs when it runs the data flow tasks that implement some derived column transformations. Any ideas on how to fix this issue? Thanks for your help!
Here is my C# code:
class MyEventListener : DefaultEvents
{
public override bool OnError(DtsObject source, int errorCode, string subComponent,
string description, string helpFile, int helpContext, string idofInterfaceWithError)
{
// Add application-specific diagnostics here.
Console.WriteLine("Error in {0}/{1} : {2}", source, subComponent, description);
return false;
}
}
class Program
{
static void Main(string[] args)
{
GetExtractsData();
}
static void GetExtractsData()
{
string pkgLocation;
Package pkg;
Application app;
DTSExecResult pkgResults;
MyEventListener eventListener = new MyEventListener();
pkgLocation = #"C:\Package.dtsx";
app = new Application();
pkg = app.LoadPackage(pkgLocation, null);
pkg.EnableConfigurations = true;
Configuration config = pkg.Configurations.Add();
config.ConfigurationType = DTSConfigurationType.ConfigFile;
config.ConfigurationString=#"C:\Extracts_Config.dtsConfig";
pkgResults = pkg.Execute(null, null, eventListener, null, null);
Console.WriteLine(pkgResults.ToString());
Console.WriteLine("The Extracts completed downloading at: " + DateTime.Now.ToString());
}

Options to manage local vs cloud development configuration settings in Visual Studio

We will use Windows Azure Websites for our basic hosting needs in the future. And since there are very specific configuration settings for cloud vs local how do you manage these settings? Take for example the following:
Local Development Server:
string path = AppSettings["StoragePath"];
<add key="StoragePath" value="c:\temp" />
Windows Azure:
string path = AppSettings["StoragePath"];
<add key="StoragePath" value="xyz" />
Do you manually change the StoragePath in the config file before each release OR is there something in code that can be done such as:
<add key="LocalStoragePath" value="c:\temp" />
<add key="BlobStoragePath" value="xyz" />
string path;
if (Azure)
{
path = AppSettings["BlobStoragePath"];
}
else
{
path = AppSettings["LocalStoragePath"];
}
If the later is possible, how can i determine if the environment is Windows Azure?
I typically create a new build configuration (called Azure).
Then in the web.config create your keys..
<add key="LocalStoragePath" value="c:\blah" />
<add key="AzureStoragePath" value="xyz" />
in your code write:
#if CONFIG == "Azure"
public const String storageKey = "AzureStoragePath";
#endif CONFIG == "Debug"
public const String storageKey = "LocalStoragePath";
#endif
And use it:
String path = AppSettings[storageKey];
public interface IConfigurationProvider { }
public class AzureConfigurationProvider : IConfigurationProvider { }
public class LocalConfigurationProvider : IConfigurationProvider { }
public static class ConfigurationProviderFactory
{
private static bool _isAzure = Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.IsAvailable;
private static Lazy<IConfigurationProvider> _provider = Lazy<IConfigurationProvider>(GetProvider);
private static IConfigurationProvider GetProvider()
{
return _isAzure ?
new AzureConfigurationProvider() :
new LocalConfigurationProvider();
}
public static IConfigurationProvider Instance
{
get { return _provider.Value; }
}
}
Assuming you're using the latest version of Web Publishing feature in VS 2010 or VS2012 you can accomplish this fairly easily with your publish profile and a web.config transform.
First, create your publish profile (right-click the project, select Publish, go through the dialog). This will be the default place to make a variety of config change anyways, such as connection strings.
Then, right-click the the .pubxml file created for your publish profile and there should be an option to add a transform. This will add a new web..config, which should appear next to the web.Debug.config/web.Release.config.
In that file you can add a transform for the app setting you want to change. The transformation value will be applied when you publish using that profile; local development will still use whatever value you want.

How to deploy a visual studio custom tool?

I have my own custom tool for Visual Studio 2008 SP1. It consists of 5 assemblies: 3 assemblies with code that are used heavily in my other projects, 1 assembly-wrapper above VS2008 SDK and an assembly with the tool.
If I'd debug my tool from visual studio, using "Run external program" option with command line "C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe" and arguments "/ranu /rootsuffix Exp" all works perfectly.
After that I'm trying to deploy it to my working VS copy, not to experimental hive, doing: gacutil /i Asm1.dll for all my assemblies and doing RegAsm Asm1.dll only for assembly with custom tool. Neither of utils prints any error, all work as planned, even registry keys appear. But my tool doesn't work (error occurred "Cannot find custom tool 'TransportGeneratorTool' on this system") even after PC restart. What did I do wrong?
Wrapper looks like that:
[ComVisible(true)]
public abstract class CustomToolBase : IVsSingleFileGenerator, IObjectWithSite
{
#region IVsSingleFileGenerator Members
int IVsSingleFileGenerator.DefaultExtension(out string pbstrDefaultExtension)
{
pbstrDefaultExtension = ".cs";
return 0;
}
int IVsSingleFileGenerator.Generate(string wszInputFilePath, string bstrInputFileContents, string wszDefaultNamespace, IntPtr[] rgbOutputFileContents, out uint pcbOutput, IVsGeneratorProgress pGenerateProgress)
{
GenerationEventArgs gea = new GenerationEventArgs(
bstrInputFileContents,
wszInputFilePath,
wszDefaultNamespace,
new ServiceProvider(Site as Microsoft.VisualStudio.OLE.Interop.IServiceProvider)
.GetService(typeof(ProjectItem)) as ProjectItem,
new GenerationProgressFacade(pGenerateProgress)
);
if (OnGenerateCode != null)
{
OnGenerateCode(this, gea);
}
byte[] bytes = gea.GetOutputCodeBytes();
int outputLength = bytes.Length;
rgbOutputFileContents[0] = Marshal.AllocCoTaskMem(outputLength);
Marshal.Copy(bytes, 0, rgbOutputFileContents[0], outputLength);
pcbOutput = (uint)outputLength;
return VSConstants.S_OK;
}
#endregion
#region IObjectWithSite Members
void IObjectWithSite.GetSite(ref Guid riid, out IntPtr ppvSite)
{
IntPtr pUnk = Marshal.GetIUnknownForObject(Site);
IntPtr intPointer = IntPtr.Zero;
Marshal.QueryInterface(pUnk, ref riid, out intPointer);
ppvSite = intPointer;
}
void IObjectWithSite.SetSite(object pUnkSite)
{
Site = pUnkSite;
}
#endregion
#region Public Members
public object Site { get; private set; }
public event EventHandler<GenerationEventArgs> OnGenerateCode;
[ComRegisterFunction]
public static void Register(Type type)
{
using (var parent = Registry.LocalMachine.OpenSubKey(#"Software\Microsoft\VisualStudio\9.0", true))
foreach (CustomToolRegistrationAttribute ourData in type.GetCustomAttributes(typeof(CustomToolRegistrationAttribute), false))
ourData.Register(x => parent.CreateSubKey(x), (x, name, value) => x.SetValue(name, value));
}
[ComUnregisterFunction]
public static void Unregister(Type type)
{
using (var parent = Registry.LocalMachine.OpenSubKey(#"Software\Microsoft\VisualStudio\9.0", true))
foreach (CustomToolRegistrationAttribute ourData in type.GetCustomAttributes(typeof(CustomToolRegistrationAttribute), false))
ourData.Unregister(x => parent.DeleteSubKey(x, false));
}
#endregion
}
My tool code:
[ComVisible(true)]
[Guid("55A6C192-D29F-4e22-84DA-DBAF314ED5C3")]
[CustomToolRegistration(ToolName, typeof(TransportGeneratorTool))]
[ProvideObject(typeof(TransportGeneratorTool))]
public class TransportGeneratorTool : CustomToolBase
{
private const string ToolName = "TransportGeneratorTool";
public TransportGeneratorTool()
{
OnGenerateCode += GenerateCode;
}
private static void GenerateCode(object s, GenerationEventArgs e)
{
try
{
var serializer = new XmlSerializer(typeof (Parser.System));
using (var reader = new StringReader(e.InputText))
using (var writer = new StringWriter(e.OutputCode))
{
Generator.System = (Parser.System) serializer.Deserialize(reader);
Generator.System.Namespace = e.Namespace;
Generator.GenerateSource(writer);
}
}
catch (Exception ex)
{
e.Progress.GenerateError(ex.ToString());
}
}
}
Resulting registry keys:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Generators]
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Generators\{FAE04EC1-301F-11D3-BF4B-00C04F79EFBC}]
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Generators\{FAE04EC1-301F-11D3-BF4B-00C04F79EFBC}\TransportGeneratorTool]
#="TransportGeneratorTool"
"CLSID"="{55a6c192-d29f-4e22-84da-dbaf314ed5c3}"
"GeneratesDesignTimeSource"=dword:00000001
"GeneratesSharedDesignTimeSource"=dword:00000001
Here is the code of my custom attribute (it is in wrapper assembly):
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class CustomToolRegistrationAttribute : RegistrationAttribute
{
public CustomToolRegistrationAttribute(string name, Type customToolType)
{
Name = name;
CustomToolType = customToolType;
}
/// <summary>
/// The type that implements the custom tool. This starts
/// as MyCustomTool by default in the template.
/// </summary>
public Type CustomToolType { get; set; }
public string Name { get; set; }
#region RegistrationAttribute abstract member implementations
public override void Register(RegistrationContext context)
{
Register(x => context.CreateKey(x), (x, key, value) => x.SetValue(key, value));
}
public void Register<T>(Func<string, T> keyCreator, Action<T, string, object> valueCreator)
{
var keyName = CreateKeyName(Name);
var key = keyCreator(keyName);
valueCreator(key, string.Empty, Name);
valueCreator(key, "CLSID", CustomToolType.GUID.ToString("B"));
valueCreator(key, "GeneratesDesignTimeSource", 1);
valueCreator(key, "GeneratesSharedDesignTimeSource", 1);
var disposable = key as IDisposable;
if (disposable != null)
disposable.Dispose();
}
private static string CreateKeyName(string name)
{
return string.Format(#"Generators\{0}\{1}", vsContextGuids.vsContextGuidVCSProject, name);
}
public override void Unregister(RegistrationContext context)
{
Unregister(context.RemoveKey);
}
public void Unregister(Action<string> keyRemover)
{
keyRemover(CreateKeyName(Name));
}
#endregion
}
My solution is to make a setup project. I get the registry settings from the pkgdef file by adding the following to the csproj file of the package:
<Target Name="GeneratePackageRegistryFiles">
<Exec Command=""$(VSSDK90Install)VisualStudioIntegration\Tools\Bin\RegPkg.exe" /root:Software\Microsoft\VisualStudio\9.0 /codebase "$(TargetPath)" /regfile:"$(OutDir)$(TargetName).reg"" />
</Target>
<PropertyGroup>
<BuildDependsOn>$(BuildDependsOn);GeneratePackageRegistryFiles;</BuildDependsOn>
</PropertyGroup>
When building look in the output directory you should find a .reg file which you can import in the setup project.
Obviously you can run the regpkg.exe from the command-line if modifying the project is not an option.
This is what I ended up with last time when I struggled to get my custom tool registered.
I hope this instruction is detailed enough and covers everything so you won't spend much time fighting it. The following MSDN article was used as a starting point. http://msdn.microsoft.com/en-US/library/bb166527(v=vs.80).aspx Unfortunately you cannot use it alone. What you really need to do is:
Make sure the assembly is signed. Why? Because otherwise you won't be able to put it into GAC at step 6 below.
To sign your assembly follow these steps:
1.1. Go to the Properties screen of the project.
1.2. Once there go to the Signing tab.
1.3. Once there check the Sign the assembly checkbox.
Make sure you know the version number of your assembly. You will need this number to specify the ASSEMBLY_VERSION parameter later.
In order to get this number open the AssemblyInfo.cs file in the Properties folder of your project and look for the line starting with: [assembly: AssemblyVersion(
Make sure you know the GUID of the generator class. You will need it to specify the GENERATOR_GUID parameter later.
In order to get this GUID open the file with the generator class and look for the Guid class-attribute that decorates this class, something like: [Guid("17799E85-421B-4684-B59E-650E34ECC718")]
Build the project
Get the public token key of the assembly. In order to do that you will have to run the following command:
sn.exe -T ASSEMBLY_FILE
You will need this information later when for PUBLIC_TOKEN_KEY.
The sn.exe file can be found in C:\Program Files\Microsoft SDKs\Windows\v8.0A\bin\sn.exe
Pay attention to the version number of the framework (v8.0A) in the filepath above. It needs to be consistent with the version of the framework used to compile the project.
Put the assembly to the GAC using the following command:
gacutil.exe /i ASSEMBLY_FILE /f
Getting registered in GAC requires administrative permissions.
The gacutil.exe file can be found in C:\Program Files\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\gacutil.exe
Pay attention to the version number of the framework (v8.0A) in the filepath above. It needs to be consistent with the version of the framework used to compile the project.
Make the following changes to the .REG (see below) file. PLEASE NOTE: that both GENERATOR_GUID and PROJECT_TYPE_GUID need to be supplied WITH curly braces: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
7.1. Fix version number of Visual Studio is used (for example: 10.0 or 9.0): VS_VERSION
7.2. Fix the GUID of the generator: GENERATOR_GUID
7.3. Fix the namespace of the assembly: NAMESPACE_NAME
7.4. Fix the generator class name: GENERATOR_TYPE_NAME
7.5. In order to register the generator the Visual Studio needs to know to which project types this generator can be applied to. So you need to get GUID's of proper project types (C#, VB.NET, etc.).
To figure out the GUID's of the project types you need to open a visual studio project file (*.csproj) in a text editor and look for GUID's in the ProjectTypeGuids XML element.
For each of these GUIDs repeat the block of last 3 entries in the .REG file replacing the PROJECT_TYPE_GUID with the a GUID just found.
7.6. Fix the extension of the file associated with the custom tool: FILE_EXTENSTION
Run the .REG file. You may need to have administrative permissions for doing this.
.REG file:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\VS_VERSION\CLSID\GENERATOR_GUID]
#="COM+ class: NAMESPACE_NAME.GENERATOR_TYPE_NAME"
"InprocServer32"="C:\\WINDOWS\\system32\\mscoree.dll"
"ThreadingModel"="Both"
"Class"="NAMESPACE_NAME.GENERATOR_TYPE_NAME"
"Assembly"="NAMESPACE_NAME, Version=ASSEMBLY_VERSION, Culture=Neutral, PublicKeyToken=PUBLIC_TOKEN_KEY"
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\VS_VERSION\Generators]
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\VS_VERSION\Generators\PROJECT_TYPE_GUID]
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\VS_VERSION\Generators\PROJECT_TYPE_GUID\\.FILE_EXTENSTION]
#="GENERATOR_TYPE_NAME"
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\VS_VERSION\Generators\PROJECT_TYPE_GUID\GENERATOR_TYPE_NAME]
#="Code generator for whatever you like"
"CLSID"="GENERATOR_GUID"
"GeneratesDesignTimeSource"=dword:00000001
PS.
Sorry for not being able to make placehoders in the REG file distinct, unfortunately the text editor that StackOverflow uses cannot distinguish its markup elements from the content.

Categories