In my C# program, I am using Microsoft.Office.Interop.Excel. With this i am reading & writing data to excel file. On one machine, even though it has Office 2007, there are seeing below exception, raises at GetComponentPath() method call.
Unhandled Exception: System.MissingMethodException: Method not found: 'System.Type System.Runtime.InteropServices.Marshal.GetTypeFromCLSID(System.GUID)'.
Here is my code:
public static string GetComponentPath(OfficeComponent _component)
{
string toReturn = string.Empty;
string _key = string.Empty;
try
{
Microsoft.Office.Interop.Excel.Application _excelApp = null;
_excelApp = new Microsoft.Office.Interop.Excel.Application();
if (_excelApp != null)
{
Console.WriteLine("Excel is installed");
}
else
{
Console.WriteLine("Excel not found.");
}
}
catch (Exception ex)
{
Console.WriteLine("Error \n" + ex.ToString());
}
return toReturn;
}
public enum OfficeComponent
{
Word,
Excel,
PowerPoint,
Outlook
}
Problem : you have developed your application in your local machine with heigher version of .NET Framework and running the same on remote pc having Lower Version of.NET Framework.
Note : if you target your application to run on Heigher Version of .NET Framework it wont run on lower versions.
Solution : you need to target it to .NET Framework Lower Version available on your remote PC to run on remote pc.
Step 1: right click on project - select properties
Step 2: change the Target Framework from .NET Framework x.x to .NET Framework x.y.
Note : where x.x is heigher and x.y is lower version available on remote pc or any lower version.
Related
I have an asp.net core API that was recently updated from .net5 to .net6.
There is a piece of code that should read a duration of an audio file. The code that seems to have worked on previous versions was this:
try
{
//
// NAudio -- Windows only
//
using var fileReader = new AudioFileReader(filePath);
return Convert.ToInt32(Math.Ceiling(fileReader.TotalTime.TotalSeconds));
}
catch (DllNotFoundException)
{
try
{
//
// LibVLCSharp is crossplatform
//
using var libVLC = new LibVLC();
using var media = new Media(libVLC, filePath, FromType.FromPath);
MediaParsedStatus parsed = Task.Run(async () => await media.Parse(MediaParseOptions.ParseNetwork, timeout: 2000).ConfigureAwait(false)).Result;
if (parsed != MediaParsedStatus.Done) throw new ArgumentException("Could not read audio file");
if (!media.Tracks.Any(t => t.TrackType == TrackType.Audio) || (media.Duration <= 100)) throw new ArgumentException("Could not read audio from file");
return Convert.ToInt32(Math.Ceiling(TimeSpan.FromMilliseconds(media.Duration).TotalSeconds));
}
catch (Exception ex) when (ex is DllNotFoundException || ex is LibVLCSharp.Shared.VLCException)
{
try
{
using var fileReader = new Mp3FileReader(filePath);
return Convert.ToInt32(Math.Ceiling(fileReader.TotalTime.TotalSeconds));
}
catch (InvalidOperationException)
{
throw new ArgumentException("Could not read audio file");
}
}
}
The application was deployed on Linux and, I don't know which part of the code did the exact calculation (I am assuming the VLC part), but since the update to .NET6, all of these fail, and since the last fallback is NAudio, we get the following exception:
Unable to load shared library 'Msacm32.dll' or one of its dependencies.
I am using Windows, but I tried running the app with WSL, and I can't get the VLC part to run either - it always throws the following exception (even after installing vlc and vlc dev SDK):
LibVLC could not be created. Make sure that you have done the following:
Installed latest LibVLC from nuget for your target platform.
Unable to load shared library 'libX11' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: liblibX11: cannot open shared object file: No such file or directory at LibVLCSharp.Shared.Core.Native.XInitThreads()
at LibVLCSharp.Shared.Core.InitializeDesktop(String libvlcDirectoryPath)
at LibVLCSharp.Shared.Helpers.MarshalUtils.CreateWithOptions(String[] options, Func`3 create)
Is there any clean way to read a duration of an audio file on all platforms?
Needless to say, NAudio works like a charm on Windows, and so does the VLC (with the proper nuget package).
If you install ffmpeg, you can do this quite easily. ffmpeg comes installed in most linux distros by default, but in case it isn't, you can install it with your favorite package manager.
sudo apt install ffmpeg
To install it in windows, you'll need to download the build files, extract it, and add it to the PATH.
Next, install Xabe.FFMpeg package in your project.
Finally, you can call the static method Xabe.FFMpeg.FFMpeg.GetMediaInfo() to get all information regarding your audio file. Here is a sample snippet that I tested on my linux machine.
using System;
using System.IO;
using Xabe.FFmpeg;
namespace Program;
public static class Program
{
public static void Main(string[] args)
{
string filename;
if (args.Length == 0)
{
Console.WriteLine("No arguments found! Provide the audio file path as argument!");
return;
}
else if (File.Exists(filename = args[0]) == false)
{
Console.WriteLine("Given file does not exist!");
return;
}
try
{
var info = FFmpeg.GetMediaInfo(filename).Result;
TimeSpan duration = info.Duration;
Console.WriteLine($"Audio file duration is {duration}");
}
catch(Exception ex)
{
Console.WriteLine(ex);
}
}
}
The error you are seeing is because we were assuming that you would display a video on linux, using X11, so we are always initializing X11. See here.
We shouldn't do that for your use case(because you may not have a GUI available). Please report the issue here : https://code.videolan.org/videolan/LibVLCSharp/-/issues
or even better, submit a pull request on github or gitlab.
As for your question of why did it work on .net 5 and not anymore, I'm not sure we have enough info to tell why, because you didn't send us the error message from that machine.
I would encourage you to take a look at atldotnet. It is a small, well maintained completely managed code / cross platform library without any external dependencies and was accurate detecting audio file duration in all of my test cases (more accurate than ffmpeg). Most common audio formats are supported.
var t = new Track(audioFilePath);
// Works the same way on any supported format (MP3, FLAC, WMA, SPC...)
System.Console.WriteLine("Duration (ms) : " + t.DurationMs);
I add an application to the Windows store. When I download and run application, everything goes alright, but when some people download and run application, so throw the exception.
Třída není zaregistrována == Class not registered
There is code:
try
{
StoreContext storeContext = Windows.Services.Store.StoreContext.GetDefault();
string[] productKinds = {"Durable", "Consumable", "UnmanagedConsumable" };
List<String> filterList = new List<string>(productKinds);
queryResult = await storeContext.GetAssociatedStoreProductsAsync(filterList);
}
catch (Exception ex)
{
MessageDialog(ex, "UpdateDatabaze");
}
Anyone who know how I might resolve this exception?
I am programming the application with target version Windows anniversary (build version 14393), which supports StoreContext class. When users download application and their Windows was not anniversary but only windows 10 with build 10586 or lowest build version, then throw exception which is described in the part called question.
I have VS2013 EE WinForms application with target .net 4.5.
When I try to execute my app under Win7 without 4.5 framework installed exception window appears (0xc000007b).
What should I set in my app settings for showing a good info window with download framework option?
I don't want to publish installation file, just want exe with dll-s so publish is not my target.
try:
http://thecodeventures.blogspot.com/2012/12/c-how-to-check-if-specific-version-of.html
reffers to msdn
http://msdn.microsoft.com/en-us/library/hh925568.aspx
private static void Get45or451FromRegistry()
{
using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full\\")) {
int releaseKey = Convert.ToInt32(ndpKey.GetValue("Release"));
if (true) {
Console.WriteLine("Version: " + CheckFor45DotVersion(releaseKey));
}
}
}
// Checking the version using >= will enable forward compatibility,
// however you should always compile your code on newer versions of
// the framework to ensure your app works the same.
private static string CheckFor45DotVersion(int releaseKey){
if ((releaseKey >= 379893)) {
return "4.5.2 or later";
}
if ((releaseKey >= 379675)) {
return "4.5.1 or later";
}
if ((releaseKey >= 378389)) {
return "4.5 or later";
}
// This line should never execute. A non-null release key should mean
// that 4.5 or later is installed.
return "No 4.5 or later version detected";
}
kind regards
you can check in registry which framework is installed ? If VS version is below to 4.5 give a message window to download that version.
you can easily find out how to check VS version installed ?
here is the link http://www.mztools.com/articles/2008/MZ2008003.aspx
I've got a C# application that I've been using for years to script remote desktop connections. It's always been built on the AxMsRdpClient3 (note the 3, which I guess is some kind of version number). There are features in AxMsRdpClient8 (version 8) that I want to be able to use, but as I understand it, this requires Remote Desktop version 8 to be installed. Not all users have that installed (or even can install it on Windows XP/Vista), though.
So as Sheng Jiang suggested, I am creating the control at runtime now and I have code that looks like this:
try
{
AxMsRdpClient8 rdp8 = new AxMsRdpClient8();
rdp8.BeginInit();
// set some properties here
rdp8.EndInit(); // throws Exception on machines without version 8 installed
}
catch (Exception ex)
{
AxMsRdpClient3 rdp3 = new AxMsRdpClient3();
rdp3.BeginInit();
// set some properties here
rdp3.EndInit();
}
As expected, rdp8.EndInit() throws an exception on machines that do not have Remote Desktop version 8 installed. The problem is that after we try to create the AxMSRDPClient8, the rdp3.EndInit() fails as well (class not registered) on older machines. If I don't attempt to create the AxMSRDPClient8 first, the AxMSRDPClient3 initializes and works correctly.
each version of RDP activeX has a different clsid. You need to detect the OS version and create an activex at runtime with the class id corresponding to the lowest OS version you plan to support.
If your code depends on late binding, better rewrite your code to work with IMsRdpClient* and IMsRdpClientNonScriptable*. For example MsRdpClient8NotSafeForScripting supports the following interfaces:
up to version 8 of IMsRdpClient*
up to version 5 of IMsRdpClientNonScriptable
IMsTscNonScriptable
IMsRdpPreferredRedirectionInfo
IMsRdpExtendedSettings
MsRdpClient3NotSafeForScripting supports
version 2 of IMsRdpClient*
IMsRdpClientNonScriptable
IMsTscNonScriptable.
if you want to detect whether your activex support a particular interface version, just cast the ActiveX's instance
to the interface. when a cast fails you know the interface is not supported.
protected void CreateRdpActiveX()
{
try
{
string clsid=GetRdpActiveXClsIdByOSVersion();
Type type = Type.GetTypeFromCLSID(clsid, true);
this.axRdp = new AxHost (type.GUID.ToString());
((ISupportInitialize)(axRdp)).BeginInit();
SuspendLayout();
this.panel1.Controls.Add(axRdp);
((ISupportInitialize)(axRdp)).EndInit();
ResumeLayout(false);
var msRdpClient8 = axRdp.GetOcx() as IMsRdpClient8;
if(msRdpClient8!=null)
{
var advancedSettings9 =msRdpClient8.AdvancedSettings9 as IMsRdpClientAdvancedSettings8;
if(advancedSettings9!=null)
advancedSettings9.BandwidthDetection=true;
}
}
catch (System.Exception ex)
{
System.Console.WriteLine(ex.Message);
}
}
The following code works fine on Windows 7 (32-bit), but when ported to 64-bit, I get an exception stating "File Not Found". I have built the project in 64-bit configuration but the issue still persists.
The issue occurs if the machine does not have Office installed.
The code is as follows:
try
{
SaveFileDialog fileDialog = new SaveFileDialog();
fileDialog.InitialDirectory = path;
// set the default extension as mdb.
fileDialog.DefaultExt = ".mdb";
// allow the user to select the file type as CSV, XML or MDB.
fileDialog.Filter = "CSV (*.csv)|*.csv|XML (*.xml)|*.xml|MDB (*.mdb)|*.mdb";
fileDialog.RestoreDirectory = true;
if (DialogResult.OK == fileDialog.ShowDialog()) // exception occured
{
this.fileNameTextBox.Text = fileDialog.FileName;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
The question here is what's the value of "path". x86 and x64 machines may have different folder configurations, e.g. Program Files (x86) is one of them. You may start with Environment.SpecialFolders enum, those paths should be valid.