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);
}
}
Related
I am trying to reference "Windows.Networking.Connectivity" classes in my desktop application. I am basically interested in handling metered connections in my app.
Basically what I am trying to do is simple:
var connectionCost = NetworkInformation.GetInternetConnectionProfile().GetConnectionCost();
if (connectionCost.NetworkCostType == NetworkCostType.Unknown
|| connectionCost.NetworkCostType == NetworkCostType.Unrestricted)
{
//Connection cost is unknown/unrestricted
}
else
{
//Metered Network
}
The only method I know of that allows a desktop application to reference UWP assemblies is by manually editing the project file and adding the following line to the csproj file:
<TargetPlatformVersion>8.0</TargetPlatformVersion>
Applying the code and "hack" works fine but the problem is that doing so will prevent my app from running on Windows 7 which I need to support.
I was wondering if there is a way to reference UWP assemblies in a desktop application without having to drop support for Windows 7.
And since for the time being I only want to check if a connection is metered, I am open to suggestions about how to get this information without referencing Windows assemblies.
I found a way to use reflection and call UWP methods without having to specify a target platform. For my case this is what I did:
var networkInfoType = Type.GetType("Windows.Networking.Connectivity.NetworkInformation, Windows, ContentType=WindowsRuntime");
var profileType = Type.GetType("Windows.Networking.Connectivity.NetworkInformation, Windows, ContentType=WindowsRuntime");
var profileObj = networkInfoType.GetTypeInfo().GetDeclaredMethod("GetInternetConnectionProfile").Invoke(null, null);
dynamic profDyn = profileObj;
var costObj = profDyn.GetConnectionCost();
dynamic dynCost = costObj;
var costType = (NetworkCostType)dynCost.NetworkCostType;
if (costType == NetworkCostType.Unknown
|| costType == NetworkCostType.Unrestricted)
{
//Connection cost is unknown/unrestricted
}
else
{
//Metered Network
}
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.
This is my code that throws an exception, it just randomly started today here is the photo :
Here is the whole page code and the error exception :
public frmWFDocumentDetail()
{
InitializeComponent();
NavigationInTransition navigateInTransition = new NavigationInTransition();
navigateInTransition.Backward = new TurnstileTransition { Mode = TurnstileTransitionMode.BackwardIn };
navigateInTransition.Forward = new TurnstileTransition { Mode = TurnstileTransitionMode.ForwardIn };
NavigationOutTransition navigateOutTransition = new NavigationOutTransition();
navigateOutTransition.Backward = new TurnstileTransition { Mode = TurnstileTransitionMode.BackwardOut };
navigateOutTransition.Forward = new TurnstileTransition { Mode = TurnstileTransitionMode.ForwardOut };
TransitionService.SetNavigationInTransition(this, navigateInTransition);
TransitionService.SetNavigationOutTransition(this, navigateOutTransition);
DataContext = App.ViewModel_WFDocumentDetailItems;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
//**this is how you pass parameters through to a new page**//
string processID = "-1";
string processName = "";
NavigationContext.QueryString.TryGetValue("processID", out processID);
NavigationContext.QueryString.TryGetValue("processName", out processName);
App.ViewModel_WFDocumentHeaderItems.LoadData("johnny", processID);
App.ViewModel_WFDocumentDetailItems.LoadData("johnny");
}
and the access violation :
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory
is corrupt.
I have read up on it, some people say it is nvidia network manager, and some people say I must set some setting like Suppress JIT optimization , and ignore gpu memory if value isn't changed... but nothing works? Can anyone please please send me in the right direction?
As requested , the full stack
i used the setting taylorjohnl gave me "Debug -> Options and Settings -> Debugging -> General -> Enable Just My Code",and then the error went right to the piece of xaml that was a syntax error, and boom fixed it and app works again :) so violation error for me was basically a reference error, hope this can help other people as well, also use expression blend in silverlight to debug xaml in the UI
I had a similar problem which in the end was resolved by submitting crash dump to MS Tech Support. Here is their response:
The gist is that The crash is a known bug in the version 5.0 of comctl32.dll (Windows Common Controls), which ships with the Windows OS. This bug will not be fixed in version 5.0 of the common controls, because that version was for applications existing prior to Windows XP. It has since been fixed in version 6.0 of comctl32.dll, which is included with Windows XP and later. Note that both versions of comctl32.dll (5.0 and 6.0) are included with every version of Windows since Windows XP. The older one is just there for backwards compatibility purposes for very old applications.
To resolve the problem, you need to change the application to have it opt into version 6.0 of comctl32.dll. Within a Windows Forms application, this is done by calling into the Application.EnableVisualStyles method at startup of the application. If you are developing within a C# project, then you can do this by adding the call prior to your Application.Run call within your application's entry point. For example:
[STAThread]
static void Main()
{
Application.EnableVisualStyles(); //Add this line
Application.Run(new Form1());
}
If you are in a Visual Basic .Net project, you can opt into this by going to your project properties, and then selecting the "Enable Application Framework" and "Enable XP Visual Styles" checkboxes on the Application property page.
Once you do this, it should resolve this particular access violation.
what is code in the InitializeComponent()? there is some class refer to null in it, (mostly is a event handler). once it is trigger, it will report AccessViolation.
I'm targetting IOS 4.3 and 5.0 with an app built against the 5.0 SDK and would like to add support for the Twitter functionality introduced in iOS5 only when the app runs on a iOS5 device. What is the recommended way to reliably test for the availability of these OS features at runtime without having your app crash?
I know you do this using respondsToSelector in Objective-C but how is it done in C#?
With recent MonoTouch versions you can use the following code:
if (UIDevice.CurrentDevice.CheckSystemVersion (5, 0)) {
window.RootViewController = navigation;
} else {
window.AddSubview (navigation.View);
}
Otherwise you can get a string from UIDevice.CurrentDevice.SystemVersion and do some checks with your own code.
Follow up to comments, including mine...
If you want to check by feature you can do something like:
MonoTouch.Twitter.TWRequest req = new MonoTouch.Twitter.TWRequest ();
if (req.Handle == IntPtr.Zero) {
Console.WriteLine ("No Twitter support before iOS5");
}
What happens is that the selector to create the TWRequest instance will return null and the .NET object will be created in an invalid (unusable) state that you can query with the Handle property. Again YMMV, testing is key :-)
Is there any API for writing a C# program that could interface with Windows update, and use it to selectively install certain updates?
I'm thinking somewhere along the lines of storing a list in a central repository of approved updates. Then the client side applications (which would have to be installed once) would interface with Windows Update to determine what updates are available, then install the ones that are on the approved list. That way the updates are still applied automatically from a client-side perspective, but I can select which updates are being applied.
This is not my role in the company by the way, I was really just wondering if there is an API for windows update and how to use it.
Add a Reference to WUApiLib to your C# project.
using WUApiLib;
protected override void OnLoad(EventArgs e){
base.OnLoad(e);
UpdateSession uSession = new UpdateSession();
IUpdateSearcher uSearcher = uSession.CreateUpdateSearcher();
uSearcher.Online = false;
try {
ISearchResult sResult = uSearcher.Search("IsInstalled=1 And IsHidden=0");
textBox1.Text = "Found " + sResult.Updates.Count + " updates" + Environment.NewLine;
foreach (IUpdate update in sResult.Updates) {
textBox1.AppendText(update.Title + Environment.NewLine);
}
}
catch (Exception ex) {
Console.WriteLine("Something went wrong: " + ex.Message);
}
}
Given you have a form with a TextBox this will give you a list of the currently installed updates. See http://msdn.microsoft.com/en-us/library/aa387102(VS.85).aspx for more documentation.
This will, however, not allow you to find KB hotfixes which are not distributed via Windows Update.
The easiest way to do what you want is using WSUS. It's free and basically lets you setup your own local windows update server where you decide which updates are "approved" for your computers. Neither the WSUS server nor the clients need to be in a domain, though it makes it easier to configure the clients if they are. If you have different sets of machines that need different sets of updates approved, that's also supported.
Not only does this accomplish your stated goal, it saves your overall network bandwidth as well by only downloading the updates once from the WSUS server.
If in your context you're allowed to use Windows Server Update Service (WSUS), it will give you access to the Microsoft.UpdateServices.Administration Namespace.
From there, you should be able to do some nice things :)
P-L right. I tried first the Christoph Grimmer-Die method, and in some case, it was not working. I guess it was due to different version of .net or OS architecture (32 or 64 bits).
Then, to be sure that my program get always the Windows Update waiting list of each of my computer domain, I did the following :
Install a serveur with WSUS (may save some internet bandwith) : http://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=5216
Add all your workstations & servers to your WSUS server
Get SimpleImpersonation Lib to run this program with different admin right (optional)
Install only the administration console component on your dev workstation and run the following program :
It will print in the console all Windows updates with UpdateInstallationStates.Downloaded
using System;
using Microsoft.UpdateServices.Administration;
using SimpleImpersonation;
namespace MAJSRS_CalendarChecker
{
class WSUS
{
public WSUS()
{
// I use impersonation to use other logon than mine. Remove the following "using" if not needed
using (Impersonation.LogonUser("mydomain.local", "admin_account_wsus", "Password", LogonType.Batch))
{
ComputerTargetScope scope = new ComputerTargetScope();
IUpdateServer server = AdminProxy.GetUpdateServer("wsus_server.mydomain.local", false, 80);
ComputerTargetCollection targets = server.GetComputerTargets(scope);
// Search
targets = server.SearchComputerTargets("any_server_name_or_ip");
// To get only on server FindTarget method
IComputerTarget target = FindTarget(targets, "any_server_name_or_ip");
Console.WriteLine(target.FullDomainName);
IUpdateSummary summary = target.GetUpdateInstallationSummary();
UpdateScope _updateScope = new UpdateScope();
// See in UpdateInstallationStates all other properties criteria
_updateScope.IncludedInstallationStates = UpdateInstallationStates.Downloaded;
UpdateInstallationInfoCollection updatesInfo = target.GetUpdateInstallationInfoPerUpdate(_updateScope);
int updateCount = updatesInfo.Count;
foreach (IUpdateInstallationInfo updateInfo in updatesInfo)
{
Console.WriteLine(updateInfo.GetUpdate().Title);
}
}
}
public IComputerTarget FindTarget(ComputerTargetCollection coll, string computername)
{
foreach (IComputerTarget target in coll)
{
if (target.FullDomainName.Contains(computername.ToLower()))
return target;
}
return null;
}
}
}