win api and c# - desktops - c#

Okay, so I found this class online that "creates" a second desktop which does not run anything (ie, explorer.exe is not called and so forth).
However, this newly created desktop refuses to shutdown and go back to the orignal desktop. I have no idea whats going on. So if someone can try it on their machine, it would be very helpful.
note: assume all win api headers have been declared and work.
The class that "locks" the current dekstop:
namespace Locker
{
class CLocker
{
public static int DesktopHandle; // Hold desktop handle.
public static int oldDesktopHandle;
public static int DesktopInputID; // Hold desktop input id.
public static int DesktopThreadID; // Hold desktop thread id.
static string DesktopName = "DL.Locker.Desktop"; // Hold the name of new created desktop.
static FileStream TaskMan; // Hold the file stream object to control task manager.
static string FastSwitching = string.Empty; // Hold the original value of fast switching i.e. welcome screen
static string ShutdownWithoutLogin = string.Empty; // Hold the original value of showinh the shutdown button on welcome screen.
/// <summary>
/// Enabled used to enable or disable the locker
/// </summary>
public static bool Enabled
{
set
{
SetProcessPriorityHigh(); // Set the process priority to high.
if (value) // Enable or disable the locker?
{
CreateNewDesktop(); // Creating new desktop.
StartProcess(Application.ExecutablePath); // Starting the locker form, to allow the user to enter login info.
}
else
{
DestroyDesktop(); // Destroy the desktop.
ExitProcess(0); // Exit the current process, if desktop attached with no process, default desktop will be activated.
}
}
}
public static bool NeedBootStrapping()
{
Console.WriteLine((GetDesktopName() != DesktopName).ToString());
return (GetDesktopName() != DesktopName);
}
static string GetDesktopName()
{
int DLength = 0, DHandle = GetThreadDesktop(GetCurrentThreadId());
StringBuilder DName = new StringBuilder();
GetUserObjectInformation(DHandle, UOI_NAME, DName, 0, ref DLength);
if (DLength != 0) GetUserObjectInformation(DHandle, UOI_NAME, DName, DLength, ref DLength);
Console.WriteLine(DName.ToString());
return (DName.ToString());
}
static void CreateNewDesktop()
{
DesktopThreadID = GetThreadDesktop(GetCurrentThreadId());
DesktopInputID = OpenInputDesktop(0, false, DESKTOP_SWITCHDESKTOP);
DesktopHandle = CreateDesktop(DesktopName, "", 0, 0, GENERIC_ALL, 0);
if (DesktopHandle != 0)
{
SetThreadDesktop(DesktopHandle);
SwitchDesktop(DesktopHandle);
}
}
public static void DestroyDesktop()
{
SwitchDesktop(DesktopInputID);
DesktopInputID = 0;
SetThreadDesktop(DesktopInputID);
DesktopThreadID = 0;
CloseDesktop(DesktopHandle);
DesktopHandle = 0;
}
static void StartProcess(string Path)
{
MessageBox.Show("Hello from startProcess");
DestroyDesktop();
}
static void SetProcessPriorityHigh()
{
SetThreadPriority(GetCurrentThread(), THREAD_BASE_PRIORITY_MAX);
SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
}
}
}
And the main() function:
static void Main()
{
if (CLocker.NeedBootStrapping())
CLocker.Enabled = true; // Check if we need boot strapping or not, if true then a new desktop will created.
else // Run application as usual.
{
MessageBox.Show("Hello, this is your new desktop");
CLocker.Enabled = false;
}
}
Update: This code does not compile. It comes up with about 40 red squiggly lines underneath the words saying "Does not exists in current context".

Dont pop a message box, which requires user input to clear, on a hidden desktop instance. That's usually the down fall of hosting UI code in services as well.
Also, it's a good idea to research any and all unmanaged API calls before just running the code.

Related

C#: Controlling a power supply using VISA libraries and the device USB-TP PIA4850. Not able to read the power supply output properly

I am tring to control a power supply (from Kikusui), using the Kikusui device, USB-TP PIA4850. I use the library, Ivi.Visa.Interop. Following is the code where I am succesfully able to control the power supply, by setting the desired voltage.
(Link to programming guide: https://www.kikusui.co.jp/kiku_manuals/P/PIA4800/english/index.html)
(Link to operation manual: https://www.kikusui.co.jp/kiku_manuals/P/PIA4850_E5.pdf)
Using Ivi.Visa.Interop;
namespace USBTPTest
{
class USBTPController
{
private IResourceManager3 rm = new ResourceManager();
private IMessage iMessage;
public USBTPController() //to get the address of the device connected and open the address if found
{
string[] adrsList = rm.FindRsrc("?*");
if (adrsList.Count() != 0)
{
Open(adrsList[0]);
}
}
public bool Open(string str)
{
string addr = str;
iMessage = (IMessage)rm.Open(addr, AccessMode.NO_LOCK, 0, "");
//iMessage.WriteString("TRM 2");
iMessage.WriteString("NODE 5");
iMessage.WriteString("CH 1");
iMessage.WriteString("REM 1");
bOpened = true;
return true;
}
public bool SetVoltage(float vol) {} //method to set the desired voltage to the power supply, when called with an appropriate argument
The set voltage is checked by a multimeter on the power supply terminals. Similarly current is also set and checked. Until here the code runs and gives the expected results.
public string ReadVOut()
{
iMessage.WriteString("VOUT?"); //Query OUT(ON/OFF) measurement value
string VOutStatus;
VOutStatus = iMessage.ReadString(1024); //Read from PIA
return VOutStatus;
}
public string ReadIOut()
{
iMessage.WriteString("IOUT?"); //Query OUT(ON/OFF) measurement value
string COutStatus;
COutStatus = iMessage.ReadString(1024); //Read from PIA
return COutStatus;
}
}
}
The problem occurs when I read the voltage/current values being outputted. Although I am able to read the values correctly, sometimes reading Voltage using ReadVOut() gives current and vice versa. I am not able to figure out if its a fault in the code or in the power supply I am connected to, or something else. And kind of help/ideas/leads would be much appreciated.

System.Runtime.InteropServices.COMException: "Inappropriate source object for this action". is identified while retrieving the connected shapes

I am trying to get the connected shapes for every shape in my page. But I am finding a strange COM exception - "Inappropriate source object for this action"
Here's my code:
using Microsoft.Office.Interop.Visio;
class Program
{
static void Main(string[] args)
{
Application visApp = new Application();
Document visDoc = visApp.Documents.Open(filePath);
// Get the first page in the sample drawing.
page = visDoc.Pages[1];
foreach (Microsoft.Office.Interop.Visio.Shape shp in page.Shapes)
{
GetConnected(shp, Microsoft.Office.Interop.Visio.VisConnectedShapesFlags.visConnectedShapesOutgoingNodes, "", null, true);
}
}
private static void GetConnected(Microsoft.Office.Interop.Visio.Shape shp, Microsoft.Office.Interop.Visio.VisConnectedShapesFlags whichConnectedShapes, string category, Microsoft.Office.Interop.Visio.Selection selection, bool addToSelection)
{
Array aryTargetIDs;
//getting an exception here during the second iteration of for loop of Main method
aryTargetIDs = shp.ConnectedShapes(whichConnectedShapes, category);
}
}
The ConnectedShapes method throws this exception for 1D shapes (ie connectors). So you just need to include this check, either prior to calling your helper method or within it as per the following:
using Visio = Microsoft.Office.Interop.Visio
private static void GetConnected(
Visio.Shape shp,
Visio.VisConnectedShapesFlags whichConnectedShapes,
string category,
Visio.Selection selection,
bool addToSelection)
{
if (shp is null)
{
throw new ArgumentNullException();
}
if (shp.OneD == 0)
{
Array aryTargetIDs = shp.ConnectedShapes(whichConnectedShapes, category);
Console.WriteLine($"{shp.Master.Name} ({shp.NameID}) - {String.Join(", ", aryTargetIDs.Cast<object>().ToArray())}");
}
}
So given a set of shapes like this:
The console output from the above code would look something like this:
Start/End (Sheet.1) - 2
Decision (Sheet.2) - 4, 6
Subprocess (Sheet.4) -
Document (Sheet.6) -

List only devices shown in 'Devices and Printers' panel

I am writing an application in C# that will run on a users PC and I want to list only the devices that are shown in the Windows "Devices and Printers" control panel, things like monitors, keyboard, mouse, speakers etc.
I can use WMI to extract a list of all devices, but is there a way to only extract only those that are shown in that part of control panel rather than the full list?
I have searched online and found nothing relating to this and I can't even find what is the criteria for a device to appear in that list.
Is it possible to access the list of those devices that are shown in that list or, if not, is there a filter that can be applied to the full list that will only show those devices?
thanks in advance
I do it with p/invoke and COM interop by enumerating the shell items in Microsoft.DevicesAndPrinters and filtering by making sure that PKEY_Devices_CategoryIds contains an item starting with PrintFax.
There's no way to boil the necessary interop definitions down to fit in an answer, but this is the logic I use to enumerate the display name, the DEVMODE name, and images of any size:
public sealed class PrinterInfo
{
public string IdName { get; }
public string DisplayName { get; }
public Bitmap Image { get; }
private PrinterInfo(string idName, string displayName, Bitmap image)
{
IdName = idName;
DisplayName = displayName;
Image = image;
}
public static IReadOnlyList<PrinterInfo> GetInstalledPrinterNamesAndImages(Size imageSize)
{
var r = new List<PrinterInfo>();
using (var folderIdList = CreateDevicesAndPrintersIDL())
{
var folder = GetShellFolder(folderIdList);
var enumerator = folder.EnumObjects(IntPtr.Zero, SHCONTF.NONFOLDERS);
for (;;)
{
// If you request more than are left, actualCount is 0, so we'll do one at a time.
var next = enumerator.Next(1, out var relativeIdList, out var actualCount);
next.ThrowIfError();
if (next == HResult.False || actualCount != 1) break; // printerChild is junk
using (relativeIdList)
using (var absoluteIdList = ILCombine(folderIdList, relativeIdList))
{
var shellItem = GetShellItem(absoluteIdList);
var idName = GetPrinterFriendlyNameIfPrinter(shellItem);
if (idName != null)
r.Add(new PrinterInfo(idName, GetDisplayName(shellItem), GetImage(shellItem, imageSize)));
}
}
}
return r;
}
private static ItemIdListSafeHandle CreateDevicesAndPrintersIDL()
{
SHGetKnownFolderIDList(FOLDERID.ControlPanelFolder, KF_FLAG.DEFAULT, IntPtr.Zero, out var controlPanelIdList).ThrowIfError();
using (controlPanelIdList)
{
GetShellFolder(controlPanelIdList).ParseDisplayName(IntPtr.Zero, null, "::{A8A91A66-3A7D-4424-8D24-04E180695C7A}", IntPtr.Zero, out var childDevicesAndPriversIdList, IntPtr.Zero);
using (childDevicesAndPriversIdList)
return ILCombine(controlPanelIdList, childDevicesAndPriversIdList);
}
}
private static string GetPrinterFriendlyNameIfPrinter(IShellItem2 shellItem)
{
// Devices_PrimaryCategory returns "Printers" for printers and faxes on Windows 10 but "Printers and faxes" on Windows 7.
using (var categoryIds = new PropVariantSafeHandle())
{
shellItem.GetProperty(PKEY.Devices_CategoryIds, categoryIds).ThrowIfError();
if (!categoryIds.ToStringVector().Any(id => id.StartsWith("PrintFax", StringComparison.OrdinalIgnoreCase)))
return null;
}
// The canonical or "friendly name" needed to match the devmode
// https://blogs.msdn.microsoft.com/asklar/2009/10/21/getting-the-printer-friendly-name-from-the-device-center-shell-folder/
// PKEY_Devices_InterfacePaths doesn't seem to ever be found, but PKEY_Devices_FriendlyName works so...
shellItem.GetString(PKEY.Devices_FriendlyName, out var friendlyName).ThrowIfError();
return friendlyName.ReadAndFree();
}
private static string GetDisplayName(IShellItem2 shellItem)
{
return shellItem.GetDisplayName(SIGDN.NORMALDISPLAY).ReadAndFree();
}
private static Bitmap GetImage(IShellItem2 shellItem, Size imageSize)
{
return ((IShellItemImageFactory)shellItem).GetImage(new POINT(imageSize.Width, imageSize.Height), SIIGBF.SIIGBF_BIGGERSIZEOK)
.CopyAndFree(); // Bitmap.FromHbitmap is useless with alpha, so make a copy
}
private static IShellFolder GetShellFolder(ItemIdListSafeHandle itemIdList)
{
SHBindToObject(IntPtr.Zero, itemIdList, null, typeof(IShellFolder).GUID, out var objShellFolder).ThrowIfError();
return (IShellFolder)objShellFolder;
}
private static IShellItem2 GetShellItem(ItemIdListSafeHandle itemIdList)
{
SHCreateItemFromIDList(itemIdList, typeof(IShellItem2).GUID, out var objShellItem).ThrowIfError();
return (IShellItem2)objShellItem;
}
}
(C# 7)
Here's a full demo you can compile: https://github.com/jnm2/example-devices-and-printers/tree/master/src
For a C# 6 version which doesn't require ValueTuple, see https://github.com/jnm2/example-devices-and-printers/tree/master/src-csharp6.
I'm happy to answer any questions.

Pin is currently opened in an incompatible sharing mode

I am currently using UWP Toolkit to navigate among app pages. There is a page that is being used for initializing and opening RaspberryPi GPIO pins. The following error occurs after navigating away from that page then trying to navigate back to it again.
The process cannot access the file because it is being used by another process .\r\n\r\nPin ' is currently opened in an incompatible sharing mode. Make sure this pin is not already in use by this application or another application
I can see that the constructor is being called each time the page is visited and hence there is an attempt to open pins that are already opened. What is the best way to overcome this issue?
You may add NavigationCacheMode = NavigationCacheMode.Required; to the ctor of the page so your app will not create a new instance of it when you navigate there.
What I always do is let a class deal with managing pins so that your user code can request pins to act on.
public class IO
{
private readonly GpioController _gpioController;
private readonly Dictionary<int, GpioPin> _pins;
public IO(GpioController gpioController)
{
_gpioController = gpioController;
_pins = new Dictionary<int, GpioPin>();
}
public GpioPin OpenPin(int pin, GpioSharingMode mode)
{
if (_pins.ContainsKey(pin))
{
var gpioPin = _pins[pin];
if (gpioPin.SharingMode == mode)
{
return gpioPin;
}
throw new ArgumentException($"Pin '{pin}' is already configured in mode '{gpioPin.SharingMode}'");
}
else
{
var gpioPin = _gpioController?.OpenPin(pin, mode);
_pins[pin] = gpioPin;
return gpioPin;
}
}
}
Then my viewmodels simply request a pin as follows
public MainViewModel()
{
_io = ServiceContainer.Instance.Get<IO>();
_brakingPin = _io.OpenPin(4, GpioSharingMode.Exclusive);
_io.SetDriveMode(_brakingPin, GpioPinDriveMode.Output);
_io.Write(_brakingPin, GpioPinValue.Low);
}

Call mobile detection class method in ASP.NET app_code folder

Summary
I have an ASP.NET 3.5 website and a mobile detection method inside a C# class file inside my app_code folder. I want to call this method which sets a cookie, then switch my master page file if it's a mobile device.
I'm using a method i got from the comment section down in this article: http://www.codeproject.com/Articles/34422/Detecting-a-mobile-browser-in-ASP-NET
This just seemed simpler than using the 51degrees method of detection since i didn't really need a high level of detection, and i didn't want to send them to a different URL, but rather just flip to a different masterpage, and the NuGet package which makes a nice easy install doesn't work for ASP.NET 3.5.
The problem i'm at currently is with calling the method.
Here's the Code
External app_code class
public static class fooBar // test method
{
public static bool ean()
{
return true;
}
}
public static class HttpRequestExt
{
#region Private Fields
// These regular expressions retrieved from http://detectmobilebrowser.com/ "Open source mobile phone detection".
private static Regex MobileBrowsers = new Regex(#"android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|symbian|treo|up\\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino", RegexOptions.IgnoreCase | RegexOptions.Multiline);
private static Regex MobileApps = new Regex(#"1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\\-(n|u)|c55\\/|capi|ccwa|cdm\\-|cell|chtm|cldc|cmd\\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\\-s|devi|dica|dmob|do(c|p)o|ds(12|\\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\\-|_)|g1 u|g560|gene|gf\\-5|g\\-mo|go(\\.w|od)|gr(ad|un)|haie|hcit|hd\\-(m|p|t)|hei\\-|hi(pt|ta)|hp( i|ip)|hs\\-c|ht(c(\\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\\-(20|go|ma)|i230|iac( |\\-|\\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\\/)|klon|kpt |kwc\\-|kyo(c|k)|le(no|xi)|lg( g|\\/(k|l|u)|50|54|e\\-|e\\/|\\-[a-w])|libw|lynx|m1\\-w|m3ga|m50\\/|ma(te|ui|xo)|mc(01|21|ca)|m\\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\\-2|po(ck|rt|se)|prox|psio|pt\\-g|qa\\-a|qc(07|12|21|32|60|\\-[2-7]|i\\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\\-|oo|p\\-)|sdk\\/|se(c(\\-|0|1)|47|mc|nd|ri)|sgh\\-|shar|sie(\\-|m)|sk\\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\\-|v\\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\\-|tdg\\-|tel(i|m)|tim\\-|t\\-mo|to(pl|sh)|ts(70|m\\-|m3|m5)|tx\\-9|up(\\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\\-|2|g)|yas\\-|your|zeto|zte\\-", RegexOptions.IgnoreCase | RegexOptions.Multiline);
#endregion
public const string ViewMobileSiteCookieName = "ViewMobile";
/// <summary>
/// Determines if the request emanated from a mobile-device client;
/// and stores the result in a cookie on the response.
/// </summary>
/// <param name="request"></param>
/// <param name="Response"></param>
/// <returns></returns>
///
public static bool IsMobileClient(this System.Web.HttpRequest request, System.Web.HttpRequest Response)
{
bool isMobile = false;
bool isCookieSet = false;
var viewMobileCookie = request.Cookies[ViewMobileSiteCookieName];
if (viewMobileCookie != null && bool.TryParse(viewMobileCookie.Value, out isMobile))
{
isCookieSet = true;
}
else if (request.Browser.IsMobileDevice)
{
isMobile = true;
}
else if (request.ServerVariables["HTTP_X_WAP_PROFILE"].IsNotEmpty())
{
isMobile = true;
}
else if
(
request.ServerVariables["HTTP_ACCEPT"].IsNotEmpty()
&&
(
request.ServerVariables["HTTP_ACCEPT"].ToLower().Contains("wap")
|| request.ServerVariables["HTTP_ACCEPT"].ToLower().Contains("wml+xml")
)
)
{
isMobile = true;
}
else if (request.ServerVariables["HTTP_USER_AGENT"].IsNotEmpty())
{
string userAgent = request.ServerVariables["HTTP_USER_AGENT"];
isMobile = ((MobileBrowsers.IsMatch(userAgent) || MobileApps.IsMatch(userAgent.Substring(0, 4))));
}
// Store the result as a cookie.
if (!isCookieSet)
Response.Cookies.Add(new HttpCookie(ViewMobileSiteCookieName, isMobile.ToString()));
return isMobile;
}
public static bool IsNotEmpty(this string instance)
{
return instance != null && instance.Length > 0;
}
}
My call to it)
Right now im doing it on the page, but i figure i'll do this in global.asax on session start?
sectionTitle.InnerHtml = fooBar.ean().ToString(); // test works
sectionTitle.InnerHtml = HttpRequestExt.IsMobileClient.ToString(); // compile error
Compile Error:
CS0119: 'SWIC.HttpRequestExt.IsMobileClient(System.Web.HttpRequest, System.Web.HttpRequest)' is a 'method', which is not valid in the given context
Do i have to somehow cast this to the current instance? Should i just be doing this differently all together?
You're trying to call a method like a property. Methods need parentheses:
HttpRequestExt.IsMobileClient().ToString()
^^
You'll also have to call it on the current request, not just statically, as it is an extension method (which takes a parameter). E.g.:
sectionTitle.InnerHtml = Page.Request.IsMobileClient(Page.Response).ToString();

Categories

Resources