I'm working on an internal company desktop app that gets distributed via an internal intranet site. The app is written in C# using Xamarin.Mac and Visual Studio for Mac and works fine locally until I compress the *.app file and upload it to the intranet site to be downloaded by end users.
When a user (including myself), downloads and launches the application it completely locks up trying to perform any actions where it interacts with the users local filesystem (No errors or warnings are displayed/no crashes are seen, it just stops executing any more code. The UI continues to update but nothing else happens).
The weird part is that if you right-click the '*.app' file, select "Show Package Contents" then browse into 'Content' > 'MacOS' and double-click the copy of app contained in there, everything works fine and without any problems.
I'm not an expert on OSX so I'm really struggling to understand what could be causing this behaviour and also what the difference is between launching a Xamarin.Forms app via the '*.app' file and the executable located inside this at 'ProgramName.app/Content/MacOS/ProgramName'.
I've checked/confirmed the app isn't being sandboxed and it's being signed/notarized using the correct distribution certificates/provisioning profiles as far as I can tell, so as far as I'm aware there shouldn't be any security restrictions preventing the required filesystem access. Unless there's something I'm missing.
Is there any way I can get more insight into what is causing this behaviour, such as any debugging tools I can use to understand/view any potential problems with the app itself/the way it's being built?
Thanks!
Managed to finally get to the bottom of this one: The issue was because of a security system Apple have in-place known as 'App Translocation'.
There's a description of this here for anyone who isn't familiar: https://lapcatsoftware.com/articles/app-translocation.html - The tl;dr is that downloaded applications are marked as 'Quarantined' and when ran they're copied to a virtual read-only file system and executed from there. This prevents the application from having any access to the local filesystem (Regardless of if the application is signed/notarized or downloaded from a 'trusted' source etc).
There are two ways to 'unquarantine' an application:
Manually move the application to a different location via Finder (e.g. Drag/drop it into '/Applications' or '~/Documents' (Note: Moving the folder the app is located in/was extracted too isn't enough - You have to physically move the *.app file itself). Apple treats this action as the user considering the application as safe and removes the quarantine flag during the move operation (This has to be done via Finder, it cannot be done via command line operations such as mv).
Run the following command from Terminal to remove the quarantine flag:
xattr -dr com.apple.quarantine '/path/to/downloaded/program.app'
You can detect if you're application is being affected by App Translocation in a number of ways, for instance:
Using 'Console' you can see the path of your executable is something like '/private/var/.../AppTranslocation/....' (This is something I spotted in the Console when previously debugging, but I didn't know enough about OSX to understand exactly what I was seeing and initial attempts to understand this didn't yield any useful information at first)
Run the command xattr /path/to/downloaded/program.app. If the following is seen in then output:
com.apple.quarantine
Then it means the application will be affected by App Translocation.
Related
I have developed a web service which monitors certain directory for PDF files.
Service was tested on different systems including several Windows Server 2012 instances and works fine.
The problem occurs when deploying to customer's server - file watcher does not raise any events.
I created a small test tool to diagnose the problem.
Besides FileSystemWatcher it also has a timer, which simply updates the list of files in the watched folder each 0.5 seconds.
Screenshot of the tool at my test server (on the left) and on customer's (on the right)
As you can see, the PDF file is displayed in the list on the right (populated on a timer event), while list on the left is empty (populated on FileSystemWatcher events).
Log on the bottom also does not show any file changes.
The customer is government organization, which has strict security setup and I guess the issue has something to do with it, but:
tool does not throw any errors (I make sure to log every possible error)
we tried running the tool as Administrator (same result)
generally, target folder contents can be read without any issues (see the screenshot)
What complicates the whole process is that I don't have direct access to the target system and can only send the executables with some instructions.
Does anybody have an idea why could this happen?
Source code of the test tool
Background:
I have a main application that needs to be able to go to the web and download DLL files associated with it (ones that we write, located on our server). It really needs to be able to download these DLL files to the application folder in "C:\Program Files\". In the past I have used System.Net.WebClient to download whatever files I wanted from the web.
The Issue
I have had a lot of trouble downloading data in the past and saving to files on a user's hard drive. I get many reports of users saying that this does not work and it is generally because of user rights issues in the program.
In the cases where it was an issue with program user rights every user could go to the exact file location on the web, download it, and then save it to the right place manually.
I want this to work like all the other programs I have seen download/install in this fassion (i.e. Firefox Pluign Updates, Flash Player, JAVA, Adobe Reader, etc). All of these work without a hitch.
The Question
Is there some code I need to use to give my downloader program special rights to the Program Files folder? Can I even do this? Is there a better class or library that I should use? Is there a different approach to downloading files I should take, such as using threads or something else to download data?
Any help here is appreciated. I want to try to stay away from third-party apps/libraries if at all possible, other than Microsoft of course, due to licensing issues, but still send any suggestions my way.
Again, other programs seem to have the rights issues and download capability figured out. I want this same capability.
The usual way to do this goes like this:
Your application detects that an update is needed.
Your application starts another (updater) application, that will download the required files and install them into Program Files. This updater application must run with administrative rights (i.e., prompt for UAC elevation in Vista/Win7). The easiest way to ensure this is to add an application manifest to that updater application.
If the user is an administrator with UAC enabled, point 2 will cause a UAC prompt to appear which must be accepted (note that the same is true for Firefox/Acrobat/etc. updaters). If the user is not an administrator, he will be asked for administrator credentials. (Note that this is a good thing: Only an administrator should be allowed to upgrade applications installed for all users.)
Your updater application does not need to be written in a special way: It can use System.Net.WebClient just like before. The application manifest will ensure that it requests the required premissions for writing to Program Files.
Note that this issue (Program Files not being writable by administrators without UAC elevation) is an operating system feature and not a programing language limitation, so you won't solve this issue just by "using a different library". If you want your application to run on Vista/Win7 and write to Program Files, you will need UAC elevation.
Check out the BITS service:
http://msdn.microsoft.com/en-us/magazine/cc188766.aspx
Writing to the Program Files directory requires UAC elevation (if the user has that enabled) on Vista/Win7. See this code sample on how to prompt users for permission: http://msdn.microsoft.com/en-us/library/aa970890.aspx
Really though, please think about designing your app so that it writes to a more appropriate place where this is no risk of accidentally overwritting a critical program file.
How about trying http://netsparkle.codeplex.com/. A port of the very successful Mac Sparkle framework http://sparkle.andymatuschak.org/.
Does it really need to be in Program Files? I had a similar problem in an application, and we've written a class to resolve non-installed assemblies by first trying to load them from a subfolder of the %usersprofile%, then by going trying to download. This can be seamless if you add you resolve method to the current app domain's AssemblyResolve event.
AppDomain.CurrentDomain.AssemblyResolve+= AssemblyResolve;
public Assembly AssemblyResolve(object sender, ResolveEventArgs args)
{
//try to get locally
//try to download
return assembly;
}
Don't do it.
Theoretically it can be done easily. you just lunch another app, that runs with administrative privileges - you can request these in configuration. In the updater app, you just connect to a secure(ssl) web site, download everything you need, the files you download must be cryptographically signed.
This can also be easily solved using ClickOnce or some other web installer, capable of updates.
What you shouldn't do is just download insecure DLL's from an unverified source and execute them.
I have an XBAP that needs to be able to burn cd's. When running from inside Visual Studio, everything works okay. However when running from a browser, the IMAPI dll reports that the environment is not supported as soon as it tries to access the drive.
I am assuming this is coming down to permissioning. I have a signed certificate which I have installed and the xbap is set to run as a full trust application (although I'm guessing that it can't be or I wouldn't be having this problem).
Currently this is all running on my local machine, however eventually I want this to be deployed to a web server (all users will already have the certificate installed on their clients).
Does anyone have any ideas as to what I've missed / done wrong?
Update:
I have tried creating a new, test certificate which I've installed in my certificate store and then signed the XBAP against it, but it makes no difference.
Really could do with some ideas if anyone has any?
Further Update:
I have created a console application which is able to burn cd's. Shelling out to this console application allows me to burn the cd from my xbap, but not from inside the xbap itself.
However, this is really not what I want. Ideally I want to have all this contained within the xbap. Failing that, is there a way to include the console application in the xbap's one click deployment?
Thanks
I believe this is not possible to do with XBAP. According to MS documentation on XBAPs,
Examples of permissions not available
in the Internet zone:
FileIOPermission - This permission controls the ability to read and write files on disk. Consequently, applications in the Internet zone cannot read files on the user's hard disk.
RegistryPermission - This permission controls the ability to read/write to the registry. Consequently, applications in the Internet zone cannot access or control state in the user's registry.
SecurityPermission.UnmanagedCode - This permission controls the ability to call native Win32 functions.
When you run your XBAP over the internet, you'll hit issue #3: trying to interop with unmanaged code.
I would recommend deploying your app as a stand-alone app with ClickOnce. That way, you can have full access to the system, but still get easy deployment and upgrades like you do with XBAP.
*edit*
One thing you could try -- and I can't guarantee it will work -- but you could have your users go into IE Internet Options, add your site to the trusted sites list. I'm betting then your CD burning code will work because it will be in the trusted zone, rather than the Internet Zone.
Try going to
HKLM\SOFTWARE\Microsoft.NETFramework\Windows Presentation Foundation\Hosting
in the registry
create a new DWORD named RunUnrestricted with value 1.
I wrote a C# application that is running well on my xp development machine.
When my client is running it on different PC, it seems to freeze on both vista and 7 machines.
I would like to know if there is any issue on running dotnet applications on vista/7.
I compiled the application for both framework 2.0 and 3.5 but it didn't help.
The log file neither doesn't help.
Is there any way to know where is the application freezing (of course, the client doesn't have VS for attaching to the application) ?
Thank you in advance for any help.
Pierre.
Generally, .NET application should run the same on any Windows version with .NET framework installed. Most common problem that occur are related to the new User Account Control policy in Vista and 7, which prevents applications from accessing areas requiring elevated privileges (which would otherwise run fine under an Administrator account in XP).
For example, if your application is trying to write configuration settings to the Program Files folder (which is a really bad idea, btw), or is using some hardcoded disk or registry paths instead of environment variables provided in .NET classes, it may fail under Vista.
To quickly check if this is an UAC privilege problem, try to run the application as an administrator (have your client right click the .exe file and select Run as Administrator). If it works, then this suggests that you need to examine your code and update it to make sure you are only accessing allowed areas.
Check this link for more information: Making apps UAC aware.
As redsquare suggested, the best way to test your application in a variety of Windows systems is to run them in several virtual machines (MS Virtual PC or VMWare Player, both of them free for download).
You do not give much information in order for us to help a great deal.
I would start by trying to recreate the issue locally on a virtual machine (vista one available here) and then profiling the app with something like memprofiler.
Ask your client to capture a process dump using Windows Task Manager,
In Task Manager, find the process that hangs.
Right click and capture a memory dump.
Then you can do some analysis on the dump to see why it hangs.
If you are not familiar with dump analysis, find someone who can help or open a support case via http://support.microsoft.com
csharp applications are supposed to run on vista/win7. This is their home:)
Your problem is not the OS. its your application.
Most probably the application is looking for a file, a folder, something on the client side that is not there and its freezing. this is my experience.
Check for project independencies and make sure you have shipped to your clients everything your project needs.
and last, distribute to one client the debug version with debug messages enable and get the feedback from their system.
I want to create a window based application in C# so that we can run it without installing the application into each and every system.
It need to connect that application through database as well.
I want to create this application so that it can be run directly through pendrive and can write into database as well.
I know how to work with database though window application but with installer only.
I have created many window application
but all runs on client machine after
Installing the deployed setup. But now
i want client need not install the
setup deployed. He can use my
application by directly clicking my
executable file
There is nothing in Windows that requires an application to be installed. That said, installation is intended to:
Make things more simple for the end user.
Setup the registry, usually for path information and uninstall information.
Initialize any initial information the software may need before it's first run.
Simply avoiding using the registry and saving files locally to your application is usually enough to make your application portable.
That said, as long as you allow the user to select a database location within your software, you should be fine. Saving the information on the pen-drive, in an .ini file for instance, would allow each computer you plug into to read these same settings.
If you expect each computer to have a difference connection string to the database, you could save your settings to the %appdata% directory. When the user plugs the pendrive back in later, his settings will still be there, and no other user will see these same settings.
The downside to the second approach, however, is that the user has no way to "uninstall" and recover the space written to %appdata% automatically. However, for most private business applications, this isn't much of a concern.
Edit: If your real question here is how to distribute an application without an installer, simply build the Release version of your application, and look in /bin/Release/ within your project. Copy these files to another location, remove any debug or unneeded files, and make sure you have all your dependencies in order.
If you just want to connect to a database, you can do that in the EXE without any kind of installer needed. How that is done would depend on which database it is, and how you are connecting to it, but generally the item that requires encoding in the EXE (or in an outboard XML file which the EXE can read) is a connection string. This connection string is probably what the installer is managing.
A good tutorial on building your first Windows application in C# can be found here:
http://msdn.microsoft.com/en-us/library/360kwx3z.aspx
If you don't know where and how to start window form application or how to connect to database or so, there are plenty tutorials and you can Google for it very easily ;)
Here are few examples:
GUI related:
Tutorial: Working with Windows Forms
- Part I
GUI Windows Forms « C# / CSharp Tutorial
Windows Forms
tutorial with C#
Databases related:
Creating a database connection
Simplest form of installation; use an if/else; when application start, it would check for some registry key (lets say, installation=done), if the value of registery key is="done", then run the else part, which means run the app. If its "notdone", then setup all initial settings and then run the app. A pseudo will go as follows:
if(HasValidRegistryKeys()) //Check if initial settings are already there
{
Runnable=true;
}
else
{
//Not installed, lets setup app settings
//Assume that the application is running for the first time.
try
{
SetupRegistry(); //Set installation=done
SetupDatabase();
//Setup more things.
Runnable=true;
}
catch()
{Runnable=false;}
}
//Run the app
if(Runnable)
{
RunApp();
}
else
{
MessageBox.Show("Some error");
}