i am running in an exception when I want to update extensions in Visual Studio 2015. Each and every time I am updating an extension I will get an file is already in use exception. I tracked this down to the file *.pkgdef.
I am running in this exception on my working pc only. This machine runs Windows 8.1 with McAfee Antivirus, Firewall and Drive Encryption. I have the feeling that drive encryption has something to do with this exception but I can not say this for sure.
I debugged VSIXInstaller and found something that I believe is a bug.
The class is ExtensionManagerService.cs in the assembly Microsoft.VisualStudio.ExtensionManager.Implementation.dll .
private void AtomicallyDeleteFiles(IEnumerable<string> filePaths, bool justMarkForDeletion)
{
foreach (FileStream fileStream in this.LockFiles(filePaths, (IList<string>) null))
{
if (justMarkForDeletion)
{
string str = fileStream.Name + ".deleteme";
File.Delete(str);
File.Move(fileStream.Name, str);
}
else
File.Delete(fileStream.Name);
fileStream.Close();
}
}
The LockFiles method is implemented as followed:
private IEnumerable<FileStream> LockFiles(IEnumerable<string> filePaths, IList<string> inUse = null)
{
List<FileStream> list = new List<FileStream>();
foreach (string path in filePaths)
{
try
{
FileAttributes attributes = File.GetAttributes(path);
if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
{
FileAttributes fileAttributes = attributes & ~FileAttributes.ReadOnly;
File.SetAttributes(path, fileAttributes);
}
FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Write, FileShare.Delete);
list.Add(fileStream);
}
catch (Exception ex)
{
if (ex is FileNotFoundException)
{
try
{
Registry.SetValue("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\VisualStudio\\Extensibility\\ExtensionSDKDeletionListStore\\", "ScanForDeleteMeExtensionSDKsAtStartup", (object) 1, RegistryValueKind.DWord);
Registry.SetValue("HKEY_CURRENT_USER\\Software\\Microsoft\\VisualStudio\\Extensibility\\ExtensionSDKDeletionListStore\\", "ScanForDeleteMeExtensionSDKsAtStartup", (object) 1, RegistryValueKind.DWord);
}
catch
{
}
}
if (inUse == null)
{
foreach (Stream stream in list)
stream.Close();
throw;
}
else
inUse.Add(path);
}
}
return (IEnumerable<FileStream>) list;
}
The exception happens at File.Move in AtomicallyDeleteFiles. I think that at that point a File.Copy was intended to be used. The file can not be moved because it was locked in the first place.
What I could not determine is why this only happens on my McAfee machine. But this problem was reported also here Can't Update or Uninstall NuGet Package Manager in VS2012 and here http://www.paraesthesia.com/archive/2013/07/30/upgrading-nuget-the-process-cannot-access-the-file-because-it.aspx/.
I do not know how can I get in touch with the Visual Studio Team. Would you consider this a bug too ? Can anyone help me reporting this ?
Regards
T4E
I think that the proper place to put feedback to Visual Studio is Microsoft Connect. It's unfortunate that VS is not open source so you can't offer them pull request. I suffer from the same issue and your finding seems reasonable -- although the fact that I too have McAfee on my machine is suspicious.
Related
I don't want to show my powerpoint addin from programs and feature in control panel after installation.
For this I tried to add systemcomponent property in registry HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall after adding this manually Add-in was successfully hide from programs and features but when I tried to do this from my code, getting an exception of type ThrowUnauthorizedAccessException (exception error message "Cannot write to the registry key") althought I am running that .exe on Admin mode. I am not figuring it out how to add this property in "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" directory using C# code.
If this is not the right solution to do this so what else I can do?
Here is my code
RegistryKey registry = Registry.CurrentUser.OpenSubKey(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", true);
foreach (var subkey in registry.GetSubKeyNames())
{
RegistryKey productKey = registry.OpenSubKey(subkey);
if (productKey != null)
{
foreach (var value in productKey.GetValueNames())
{
string keyValue = Convert.ToString(productKey.GetValue(value));
if (keyValue.ToLower().Contains("myaddin"))
{
try
{
productKey.SetValue("SystemComponent", 1, RegistryValueKind.DWord);
productKey.Close();
return;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
}
I have the following code and my code does not catch the exception.
In my code I am trying to read all the files for which the access is granted.
var pathsToSearch = new Queue<string>();
var foundFiles = new List<string>();
pathsToSearch.Enqueue(startFolder);
while (pathsToSearch.Count > 0) {
var dir = pathsToSearch.Dequeue();
try {
var files = Directory.GetFiles(dir);
foreach (var file in Directory.GetFiles(dir)) {
foundFiles.Add(file);
}
foreach (var subDir in Directory.GetDirectories(dir)) {
pathsToSearch.Enqueue(subDir);
}
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine(e);
}
}
Why does the try catch not work properly or is there some mistake in my code ?
It sounds like you're running your program from Visual Studio, which catches First Chance Exceptions by default. You can turn off this option in Visual Studio. I believe this is under Debug > Exceptions, but you may also be able to disable this from the popup dialog that displays the exception.
Here's a Microsoft article that might be helpful: Understanding Exceptions while debugging with Visual Studio
I'm trying to code a proof of concept, with Xamarin android.
A sort of EMM tool, i.e. an application which will be in charge of installing other applications and managing the device.
So Android Marshmallow is a good place to start with android for work features.
My app is a Device Owner, therefore it should have no problem silently installing other applications. It can download an apk from a website without any problem. But when I try to install it, it throws a "Files still open" exception despite calling all Close() methods.
I have taken my code from the excellent android-testdpc github example here.
I have changed it to work in C# with Xamarin.
Here is my code:
public static bool InstallPackage(Context context, Handler handler, InputStream input, String packageName)
{
try
{
PackageInstaller packageInstaller = context.PackageManager.PackageInstaller;
PackageInstaller.SessionParams param = new PackageInstaller.SessionParams(PackageInstallMode.FullInstall);
param.SetAppPackageName(packageName);
// set params
int sessionId = packageInstaller.CreateSession(param);
PackageInstaller.Session session = packageInstaller.OpenSession(sessionId);
using (System.IO.Stream output = session.OpenWrite("COSU", 0, -1))
{
byte[] buffer = new byte[65536];
int c;
while ((c = input.Read(buffer)) != -1)
{
output.Write(buffer, 0, c);
}
session.Fsync(output);
input.Close();
output.Close();
}
session.Commit(createIntentSender(context, sessionId)); // this line throws exception 'Files stil open'
return true;
}
catch (Exception ex)
{
Log.Error(TAG, "Error installing package: " + packageName, ex);
handler.SendMessage(handler.ObtainMessage(Common.MSG_INSTALL_FAIL,
packageName));
return false;
}
}
I'm stuck with this for the moment. If I have the time, I will try to install Android Studio and test my code in Java to see if the problem comes from Xamarin.
If someone has any clue for my problem, I will greatly appreciate the help.
SecurityException : if streams opened through openWrite(String, long, long) are still open.
The Java peer object is not closed yet, this is how I force it for the PackageInstaller.Session.Commit:
var input = Assets.Open(packageName);
var packageInstaller = PackageManager.PackageInstaller;
var sessionParams = new PackageInstaller.SessionParams(PackageInstallMode.FullInstall);
sessionParams.SetAppPackageName(packageName);
int sessionId = packageInstaller.CreateSession(sessionParams);
var session = packageInstaller.OpenSession(sessionId);
using (var output = session.OpenWrite(packageName, 0, -1))
{
input.CopyTo(output);
session.Fsync(output);
foreach (var name in session.GetNames())
Log.Debug("Installer", name);
output.Close();
output.Dispose();
input.Close();
input.Dispose();
GC.Collect();
}
var pendingIntent = PendingIntent.GetBroadcast(BaseContext, sessionId, new Intent(Intent.ActionInstallPackage), 0);
session.Commit(pendingIntent.IntentSender);
I know this question seems strange.
I use .NET Micro Framework to write a small program in C# that use the default emulator to emulate a flash light using 5 buttons on the emulator, using interruptport to raise events.
I coded so that when i pressed the bottom button, all the records stored in an arraylist usagelog will be printed out to a txt file. Very simple and straightforward, i made a Streamwriter instance
StreamWriter sw = new StreamWriter(#"c:\temp.txt");
But then it throws "An unhandled exception of type 'System.ArgumentException' occurred in System.IO.dll" at this line.
I can't fix this, and I can't understand why there's an argument exception here. The code works fine for a console project in visual C#, but it doesn't in Micro Framework.
The problem you are having is the because the FileSystem is different between Windows and the MicroFramework. I was able to get it to run on the Emulator by using some Directory Functions to determine the available directorys.
public static void Main()
{
string d = Directory.GetCurrentDirectory();
string[] directorys = Directory.GetDirectories(d);
foreach (var item in directorys )
{
Debug.Print(item);
}
try
{
using (StreamWriter sw = new StreamWriter("\\WINFS\\temp.txt"))
{
sw.WriteLine("Good Evening");
sw.Close();
}
}
catch (Exception ex)
{
throw ex;
}
}
In the Emulator I came up with
[0]: "\\ROOT"
[1]: "\\WINFS"
ROOT did not work but WINFS did.
I need the reference system32/shell32.dll as I use some shell functions to read out the recycling bin. I tried "Add Reference --> COM --> Microsoft Shell Controls and Automatation" and "Add Reference --> Browse ---> [going to the system32/shell32.dll directly]. Both adds the shell32 reference to my references. But when I look at the properties, I see the path of the reference looks like this: "C:\Users\Tim\Documents\Visual Studio 2008\Projects\Wing\FileWing\obj\Debug\Interop.Shell32.dll" ...
I'll not deploy this \obj\Debug\ path to my installer. So how can I reference the end-users shell32.dll directly? Is there a way? Why does VS2008 create this strange path? Can I change this path so it doesn't sit in this strange subfolder?
Hmmm. Okay after revisiting PInvoke, I'm sure that I don't quite get it :-/
Let me illustrate the code I need to handle. I'm digging though the recycling bin and seek for a item that I want to recover. Is there any way NOT fighting though the PInvoke to get this done?
private void recoverRecyclerBinEntry(string fileName, int size)
{
try
{
Shell Shl = new Shell();
Folder Recycler = Shl.NameSpace(10);
// scans through all the recyclers entries till the one to recover has been found
for (int i = 0; i < Recycler.Items().Count; i++)
{
FolderItem FI = Recycler.Items().Item(i);
string FileName = Recycler.GetDetailsOf(FI, 0);
if (Path.GetExtension(FileName) == "")
FileName += Path.GetExtension(FI.Path);
//Necessary for systems with hidden file extensions.
string FilePath = Recycler.GetDetailsOf(FI, 1);
string combinedPath = Path.Combine(FilePath, FileName);
if (size == FI.Size && fileName == combinedPath)
{
Debug.Write("Match found. Restoring " + combinedPath + "...");
Undelete(FI);
Debug.WriteLine("done.");
}
else
{
Debug.WriteLine("No match");
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
Debug.WriteLine(ex.StackTrace);
}
}
private bool Undelete(FolderItem Item)
{
try
{
foreach (FolderItemVerb FIVerb in Item.Verbs())
{
if (
(FIVerb.Name.ToUpper().Contains("WIEDERHERSTELLEN")) ||
(FIVerb.Name.ToUpper().Contains("ESTORE")) ||
(FIVerb.Name.ToUpper().Contains("NDELETE"))
)
{
FIVerb.DoIt();
return true;
}
}
//execute the first one:
Item.Verbs().Item(0).DoIt();
return true;
}
catch (Exception)
{
Debug.WriteLine("ERROR undeleting");
return false;
}
}
I believe you are looking for P/Invoke (Platform Invoke)
Once you get the method for including and using the DLLs down, you can visit pinvoke.net to get specific code snippets for using certain methods.
Are you just using DllImport to access functionality in shell32/kernel32? If so, you don't need to add a reference.
For example:
[DllImport("KERNEL32.DLL", EntryPoint="MoveFileW", SetLastError=true,
CharSet=CharSet.Unicode, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
public static extern bool MoveFile(String src, String dst);
Here's a tutorial on using platform invoke and here's an MSDN article.
After you add the dll reference using VS 2008, you can open the properties for the .dll.
Make sure Copy Local is set to True.
If that doesn't work another solution is to add the .dll as an item to you project, and make is as content, and tell it to copy to the output directory.