Delivering Server Side Windows exe application via Asp.net - c#

I have a strange requirement from a client that I have been battling with for weeks.
The client has a standalone Winform exe and web applications sitting on Windows 2012 Server. The Plan is to incorporate the exe application into the Web applications so that it can be rendered through the browser or called via a hyperlink. The exe application is portable. Web applications run on .NET framework 3.5,written in C#.
Due to high security restrictions on the server none of my attempts seem to work. When I click on the button on the page nothing happens.
I am now exploring delivering the exe application to end users via WebDAV. Any ideas would be helpful
I have tried the following:
On web.config I set the path.
<appSettings>
<add key="EXELOC" value="C:\Temp\addons\"/>
</appSettings>
On the aspx page I have a button that calls the application.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Diagnostics;
using System.Configuration;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnStart_Click(object sender, EventArgs e)
{
string locn = ConfigurationManager.AppSettings["EXELOC"];
Process myProcess = new Process();
try
{
myProcess.StartInfo.UseShellExecute = True;
myProcess.StartInfo.FileName = locn + "Application.exe";
myProcess.StartInfo.CreateNoWindow = true;
myProcess.Start();
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
}
I set permissions for IIS Application pool to access the folder where the exe is located:
$IncomingPath = "C:\Temp\Addons"
$Acl = Get-Acl $IncomingPath
$Ar = New-Object system.security.accesscontrol.filesystemaccessrule("IIS AppPool\addons","FullControl","ContainerInherit, ObjectInherit", "None", "Allow")
$Acl.SetAccessRule($Ar)
Set-Acl $IncomingPath $Acl
I have also attempted to utilize URI:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\Ach]
#="URL:Ach Protocol"
"URL Protocol"=""
[HKEY_CLASSES_ROOT\Ach\DefaultIcon]
#="C:\\Temp\\addons\\Application.exe"
[HKEY_CLASSES_ROOT\Ach\shell]
[HKEY_CLASSES_ROOT\Ach\shell\open]
[HKEY_CLASSES_ROOT\Ach\shell\open\command]
#="\"C:\\Temp\\addons\\Application.exe\" /u \"%1\""
I have also attempted setting the application UNC and calling via Javascript:
<script type="text/javascript" language="javascript">
function RunFile() {
WshShell = new ActiveXObject("WScript.Shell");
WshShell.Run("\\\\192.168.5.8\\Applications\\Application.bat", 1,false);
}
</script>
Nothing is working.

It is time to tell the client that what he WANTS does not matter unless he is willing to pay for redeveloping a whole platform, which means tens of millions in costs. This simply is not how things work, regardless what he wants. .Exe files running on the server will not magically transfer their output to the browser.

Related

Copy to clipboard in ASP.NET

This copy button functionality is working in localhost. But when deploy it into server it's not working on server side.
protected void btnCopy_Click(object sender, EventArgs e)
{
try
{
Thread myth;
myth = new Thread(new System.Threading.ThreadStart(CallSaveDialog));
myth.ApartmentState = ApartmentState.STA;
myth.Start();
lblok.Text = "URL Copied to Clipboard, Use CTRL+V to Paste";
}
catch (Exception ex)
{
Class_login abc = new Class_login();
abc.writeerrorlog(ex.Message);
}
}
void CallSaveDialog() { System.Windows.Forms.Clipboard.SetText(TxtUrl.Text); }
This code:
System.Windows.Forms.Clipboard.SetText(TxtUrl.Text);
Runs on the web server. It sets the text to the clipboard of the user executing your web application, which usually is someone named IIS AppPool\Sitename. This user is not the visitor of your website, it is the server process that is running your .NET code.
It works on your development machine ("localhost"), because IIS Express runs as your user.
The solution is to do this using JavaScript: How do I copy to the clipboard in JavaScript?

Launching a Windows 10 Store app from C# executable

So here's the gist of my problem: I have a keyboard where I can assign macros and/or launch programs from. I want to include a couple Win10 and Steam applications in that list. So I opted to build an executable "launcher", so to speak.
The code is simplistic in nature. I got Steam url's to work by placing the steam url into Process.Start("steam://rungameid/#####"). I cannot, however, figure out how to get Win10 apps to work. Here's my class:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Process.Start(#"explorer.exe shell:AppsFolder\4DF9E0F8.Netflix_mcm4njqhnhss8!Netflix.App");
Process.Start(#"shell:AppsFolder\4DF9E0F8.Netflix_mcm4njqhnhss8!Netflix.App");
Process.Start("netflix://");
Application.Exit();
}
}
Each line of Process.Start() is what I've tried, to no avail.
The bottom line I attempted from this answer, which also did not work
The first line, I can put that in a Run box or from the command line saDand it will launch Netflix, but from the C# application, I get a "System cannot find the file" exception.
Thanks for any direction!
Can you please check if you have installed this app and name you enter in the Process.Start(“ ”) is correct, You can find the names when you open the registry key HKEY_CLASSES_ROOT\Extensions\ContractId\Windows.Protocol\PackageId. Look for the CustomProperties key. It has an attribute Name. I use the below sample to open my photos, It works fine.
private void Form4_Load(object sender, EventArgs e)
{
button2_Click(null,null);
}
private void button2_Click(object sender, EventArgs e)
{
Process.Start("ms-photos://");
}
Instead of
Process.Start(
#"explorer.exe shell:AppsFolder\4DF9E0F8.Netflix_mcm4njqhnhss8!Netflix.App"
);
Do this
Process.Start(
"explorer.exe",
"shell:AppsFolder\4DF9E0F8.Netflix_mcm4njqhnhss8!Netflix.App"
);
I was having the same problem. Currently unable to launch a windows app store application from c#. I used a work around for now. I made a bat file that navigates to the desktop and launches the desktop shortcut link. Then I call my bat file which launches the app store application.
Example of BAT file:
cd\
cd Users\d1\OneDrive\Desktop
"XYZ Games - Shortcut.lnk"
Example Code C#:
Process proc = new Process();
proc.StartInfo.FileName = "launcherXYZGames.bat";
proc.Start();

How to pass data from windows application to web application?

I have a windows application and i want to open my web application from this windows application. My Windows application will generate a key and machine code after authorization and will save the key and machine code in to database among active users. Now i want to send this key to browser so that my web application can identify the user with his machine.
How can i do this?
i cannot use URL because the user will be able to copy the URL and use my web application from another machine. I must restrict it.
Is there any other way?
There are Two Ways to transfer winform data to web applications
If you want to transfer the data to IE then You can Use
1)MSHtml.dll
code
InternetExplorer TargetIE = null;
IHTMLDocument2 document = null;
//Check whether the IE is opened
foreach (InternetExplorer internetExplorer in new ShellWindows())
{
if (internetExplorer.Document is HTMLDocument)
{
TargetIE = internetExplorer;
break;
}
}
2) If you want to transfer data from winform to any web browser my personal advice to you please use selenium for this.
download the respective dll and driver for respective drivers from this site help
Code
using OpenQA.Selenium;
using OpenQA.Selenium.IE;
using OpenQA.Selenium.Support.UI;
using OpenQA.Selenium.Chrome;
namespace WindowsFormsChrome
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// download the chrome driver
IWebDriver driver = new ChromeDriver(#"C:\Users\Downloads\chromedriver");
driver.Navigate().GoToUrl("http://www.yahoo.com");
IWebElement myField = driver.FindElement(By.Id("txtUserName"));
myField.SendKeys("UserName");
IWebElement myField = driver.FindElement(By.Id("txtPassword"));
myField.SendKeys("Password");
IWebElement myField = driver.FindElement(By.Id("btnLogin"));
myField.click()
}
}
}
this second part work for all browser yoou just replace chromeDriver class as per you want.
you can POST data using c#
http://msdn.microsoft.com/en-us/library/debx8sh9(v=vs.110).aspx
see also this post in stackoverflow
How to post data to a website
You can write an ashx handler and pass your data (or some reference to your data) from your windows application. Here is an example how this can be done :
how to call ASHX handler and getting the result back

"ClickOnce does not support the request execution level 'requireAdministrator.'"

So I was writing an application that requires access to the registry.
I had not touched any build settings, wanting to get the thing working before I added the other touches, such as a description or name.
Out of the blue, I get an error that will not go away. ClickOnce does not support the request execution level 'requireAdministrator'. Now, I hadn't touched ClickOnce in this application. All I had done was include a manifest file requesting these permissions.
My problem now is that this error will not go away, and I cannot compile my program. Any advice on what to do? (Side note: I am about to go to bed, so I will check this tomorrow afternoon).
Edit: This comment gives a good answer, too.
Click once appears to get enabled whenever you click "Publish", whether you want it to or not! If you are using "requireAdministrator" then it appears that you cannot use ClickOnce, and therefore cannot "Publish" your project.
Original:
Turns out that under the Security tab, "Enable ClickOnce security settings" was checked. Even though I didn't check it.
Anyway, unchecking that stopped ClickOnce giving me errors. That took a while to find...
I know this an old question but I came here two years later so:
You can disable the ClicKOnce from the Security tab on project properites to help the issue; see below:
If you ever use the publishing wizard, or 'Publish Now', the click-once checkbox gets automatically selected...
I know this is old but I stumbled across it looking for answers. In my case, I AM using the publish function and I need to keep using it. I also need access to admin capabilities. So for that reason, none of the above answers worked for me.
I ended up adding a method to the very start of my application that checks if it's being run as an administrator and if it isn't, relaunch itself as an admin. To do this, you need the following references added.
using System;
using System.Diagnostics;
using System.Reflection;
using System.Security.Principal;
Then you will need to put this somewhere that your main method has handy access to. I'm using WPF so I added it to MainWindow.xaml.cs but you can add it anywhere early on in your code. Just remember to add "static" to these methods should you need it.
private void AdminRelauncher()
{
if (!IsRunAsAdmin())
{
ProcessStartInfo proc = new ProcessStartInfo();
proc.UseShellExecute = true;
proc.WorkingDirectory = Environment.CurrentDirectory;
proc.FileName = Assembly.GetEntryAssembly().CodeBase;
proc.Verb = "runas";
try
{
Process.Start(proc);
Application.Current.Shutdown();
}
catch(Exception ex)
{
Console.WriteLine("This program must be run as an administrator! \n\n" + ex.ToString());
}
}
}
private bool IsRunAsAdmin()
{
try
{
WindowsIdentity id = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(id);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
catch (Exception)
{
return false;
}
}
Lastly, at the start of your program, add a reference to the method. In my case, I added it to MainWindow but adding it to Main works too.
public MainWindow()
{
InitializeComponent();
AdminRelauncher(); //This is the only important line here, add it to a place it gets run early on.
}
Hope this helps!
For .NET Core and .NET 5+
If you're stumbling upon this in the 20s, this is how you would change the above to work with .NET Core and .NET 5+
The only function that needs changing is the AdminRelauncher and it should look like this instead.
private static void AdminRelauncher()
{
if (!IsRunAsAdmin())
{
ProcessStartInfo proc = new ProcessStartInfo();
proc.UseShellExecute = true;
proc.WorkingDirectory = Environment.CurrentDirectory;
proc.FileName = Assembly.GetEntryAssembly().Location.Replace(".dll", ".exe");
proc.Verb = "runas";
try
{
Process.Start(proc);
Environment.Exit(0);
}
catch (Exception ex)
{
Console.WriteLine("This program must be run as an administrator! \n\n" + ex.ToString());
}
}
}
The only big changes is as someone pointed out Application isn't always available. So Environment.Exit(0) can replace it and the filename needs to replace .exe with .dll. This has been tested as of .NET 6
For those who use uncheck "Enable ClickOnce security settings" can't work, to try the method I find.
First, leave your app.manifest requestedExecutionLevel item as is:
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
And then you edit your Program.cs file like this:
using System;
using System.Diagnostics;
using System.Reflection;
using System.Security.Principal;
using System.Windows.Forms;
restruct main method like:
static void Main()
{
var wi = WindowsIdentity.GetCurrent();
var wp = new WindowsPrincipal(wi);
bool runAsAdmin = wp.IsInRole(WindowsBuiltInRole.Administrator);
if (!runAsAdmin)
{
// It is not possible to launch a ClickOnce app as administrator directly,
// so instead we launch the app as administrator in a new process.
var processInfo = new ProcessStartInfo(Assembly.GetExecutingAssembly().CodeBase);
// The following properties run the new process as administrator
processInfo.UseShellExecute = true;
processInfo.Verb = "runas";
// Start the new process
try
{
Process.Start(processInfo);
}
catch (Exception)
{
// The user did not allow the application to run as administrator
MessageBox.Show("Sorry, but I don't seem to be able to start " +
"this program with administrator rights!");
}
// Shut down the current process
Application.Exit();
}
else
{
// We are running as administrator
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
It works on Windows 10 and Visual Studio 2019!
This action can be achieved by selecting "Enable ClickOnce security settings" (since it cannot be "unchecked" during a Publish, as stated) and then by selecting "This is a partial trust application". "Local Intranet" will be automatically selected in the drop-down menu which is perfectly fine.
Save your changes, Publish the application, done-skis. :-)
I have the same problem s I resolve it by unchecking the "Enable ClickOnce security settings"
To Find this option in Visual Studio Right Click on your Project ==>properties==>Select Security==> Enable ClickOnce security settings (This option was already checked so I unchecked it and my problem get resolved).
Here is the code snippet for VB.NET
If Not New WindowsPrincipal(WindowsIdentity.GetCurrent).IsInRole(WindowsBuiltInRole.Administrator) Then
Process.Start(New ProcessStartInfo With { _
.UseShellExecute = True, _
.WorkingDirectory = Environment.CurrentDirectory, _
.FileName = Assembly.GetEntryAssembly.CodeBase, _
.Verb = "runas"})
EDIT: But if you deploy in this way, some AV-Software blocks your code.
For anyone who's run into this, I thought I'd contribute what ended up working for me.
Yep, the 'Enable ClickOnce security settings' option automatically gets re-checked, if you un-check it, when you do Build > Publish .
For me, I don't need to 'Publish' -- it's a simple, portable .exe that creates Scheduled Tasks for my users and I needed to make sure it elevated, even when logged-in as an Administrator.
So I just grabbed my latest .exe from \bin\Release and that's what gets deployed on my clients' systems.
Worked just as expected -- i.e. when I put it on a system w/ UAC enabled/at its highest setting, the .exe has the 'shield' on it, and when I run it, even when logged-in as an Administrator, it elevates and I get the UAC prompt.
My little task scheduler app is now able to create the task without getting an 'Access Denied' error (which previously, could only be worked-around by right-clicking the .exe and clicking Run as Administrator).
Take a look in your app.Manifest file and you'll see this:
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
There's instructions there in the comments, but just deleting the "requireAdministrator" and insert this in is place solved the problem for me:
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
just
Imports System.security
and
U will get no error and your application will be run as admin

webService Error

I am using Log Me In Rescue API to pull some reports from their web service (consumed as a web reference via Visual Studio 2010).
the report works.
However, when I try to run another report it gives me a:
getReport_PollRateExceeded
I spoke to Log Me In Rescue tech support staff, and they stated this is not an issue with their API, it's an issue with the code that i'm using. They had no limits on the number of reports you could pull from the server (they even allow you to do it real time).
I am querying their server only once ever 30 or so seconds, so i can't possibly be going over any set limit in .NET that i can think off.
The web service API can be found here:
https://secure.logmeinrescue.com/API/API.asmx
Their Wiki is here:
http://logmeinwiki.com/wiki/Rescue:API
The code i'm using is:
private void myReport_DoWork(object sender, DoWorkEventArgs e)
{
LMIR.getReportRet response = new LMIR.getReportRet();
while (response.ToString() != "getReport_OK")
{
response = proxy.getReport(iTechID, NODE_REF.NODE, sAuthCodes, out sReports);
}
}
I do not call that worker process again, until the user REQUESTS it, i even disable the request button in favor of a progress bar, waiting for the runworkercompleted() routine to finish.
But, sure enough, if i request within that 30 second limit, i receive the pollRateExceeded.
So i'm a b it confused.
Is this something that can be fixed in the app.config file?
I have since created a short program:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net;
using System.Web;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
using testLMIR.LMIR;
using System.Collections;
using System.Text.RegularExpressions;
namespace testLMIR
{
public partial class Form1 : Form
{
string sUser = "";
string sPass = "";
int iNodeID = 74249;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
LMIR.API proxy = new LMIR.API();
proxy.CookieContainer = new CookieContainer();
sUser = textBox1.Text.ToString();
sPass = textBox2.Text.ToString();
loginRet oLogin = proxy.login(sUser, sPass);
Console.WriteLine(oLogin.ToString());
string sAuthCode = "";
requestAuthCodeRet oAuthCodeReq = proxy.requestAuthCode(sUser, sPass, out sAuthCode);
string sReport = "";
getReportRet oGetReport = proxy.getReport(iNodeID,NODE_REF.NODE, sAuthCode, out sReport);
Console.WriteLine(oGetReport + "<br />");
Thread.Sleep(10000);
oGetReport = proxy.getReport(iNodeID, NODE_REF.NODE, sAuthCode, out sReport);
Console.WriteLine(oGetReport + "<br />");
Thread.Sleep(10000);
oGetReport = proxy.getReport(iNodeID, NODE_REF.NODE, sAuthCode, out sReport);
Console.WriteLine(oGetReport + "<br />");
Thread.Sleep(10000);
}
}
}
This program will take the login from 2 text boxes on the form, and take action when the button is pressed. Here's the results:
login_OK
getReport_OK<br />
getReport_PollRateExceeded<br />
getReport_PollRateExceeded<br />
If i'm reading this information correctly, i can see that even 30 seconds later, i still couldn't pull the report.
I highly doubt this is a limitation of the program, no?
Tight looping like that without any termination point other than success looks like a bad idea to me. What if the authentication has changed, for example? You'd hammer the service as hard as you could. I'd have a maximum retry limit if I were you. I'd also add some logging into your code, so you can see how often you do need to retry.
However, if the tech support staff claim that they don't have a limit, but it looks like you do, it's easy enough to find out for sure: log the traffic. Use Wireshark or Fiddler to log requests and responses. If you can show that the "PollRateExceeded" error is definitely from their service, I would certainly hope they'd look into that.
I suggest you write a short program which just pulls the report twice, ten seconds apart. If that does work, then you need to work out why it doesn't work for you in your normal code. If it doesn't work, send them that code, which should be short and complete. Give them the network trace at the same time. It'll be hard for them to argue with that.
According to the LMIR engineering team, the pollrateexceeded does indeed exist; you cannot request more than 1 piece of information in a 60 second period; only PinCodes will work with that. Anything else is 1 request per minute. No way around that, at this time.

Categories

Resources