private void Deploy(DebugPort port) { Debug.Assert(port != null && !port.IsLocalPort); VsPackage.MessageCentre.InternalErrorMsg(DiagnosticStrings.StartDeployAssemblies); CorDebugProcess process = null; bool fDeviceFound = false; VsPackage.MessageCentre.DeploymentMsg(DiagnosticStrings.StartingDeviceDeployment); for (int retries = 0; retries < 60; retries++) { VsPackage.MessageCentre.DeploymentMsg(String.Format(DiagnosticStrings.Iteration, retries)); try { process = GetDeviceProcess(); if (process != null) { switch (port.PortFilter) { case PortFilter.Serial: case PortFilter.Usb: case PortFilter.TcpIp: //test the connection. This doesn't tell you if the connection will fail during the AttachToEngine, //but it's a pretty good guess. VsPackage.MessageCentre.DeploymentMsg(String.Format(DiagnosticStrings.OpeningPort, process.PortDefinition.Port)); fDeviceFound = process.PortDefinition.TryToOpen(); if (!fDeviceFound) { VsPackage.MessageCentre.DeploymentMsg(String.Format(DiagnosticStrings.PortNotFound, process.PortDefinition.Port)); } break; default: SetDeployFailure(string.Format("Device {0} has an unsupported/unexpected port type", this.DeployDeviceDescription)); return; } if (fDeviceFound) { break; } } } catch (IOException) { } Thread.Sleep(500); } if (!fDeviceFound || process == null) { SetDeployFailure(string.Format("Device not found or cannot be opened - {0}", this.DeployDeviceDescription)); return; } VsPackage.MessageCentre.DeploymentMsg(DiagnosticStrings.AttachingEngine); Engine engine = process.AttachToEngine(); if (engine == null) { VsPackage.MessageCentre.DeploymentMsg(DiagnosticStrings.CannotAttachEngine); SetDeployFailure(string.Format(DiagnosticStrings.UnableToCommunicate, this.DeployDeviceDescription)); return; } VsPackage.MessageCentre.DeploymentMsg(DiagnosticStrings.EngineAttached); try { VsPackage.MessageCentre.DeploymentMsg(DiagnosticStrings.QueryingDeviceAssemblies); ArrayList assemblies = new ArrayList(); Hashtable systemAssemblies = new Hashtable(); //Ensure Assemblies are loaded if (process.IsDeviceInInitializeState()) { engine.ResumeExecution(); Thread.Sleep(200); while (process.IsDeviceInInitializeState()) { VsPackage.MessageCentre.DeploymentMsg(DiagnosticStrings.WaitingInitialize); //need to break out of this or timeout or something? Thread.Sleep(200); } } WireProtocol.Commands.Debugging_Resolve_Assembly[] assms = engine.ResolveAllAssemblies(); // find out which are the system assemblies // we will insert each system assemblies in a hash table where the value will be the assembly version foreach (Debugging_Resolve_Assembly resolvedAssembly in assms) { VsPackage.MessageCentre.DeploymentMsg(String.Format(DiagnosticStrings.FoundAssembly, resolvedAssembly.m_reply.Name, resolvedAssembly.m_reply.m_version.ToString())); if ((resolvedAssembly.m_reply.m_flags & Debugging_Resolve_Assembly.Reply.c_Deployed) == 0) { systemAssemblies[resolvedAssembly.m_reply.Name.ToLower()] = resolvedAssembly.m_reply.m_version; } } string[] pes = m_project.GetDependencies(true, true, engine.IsTargetBigEndian); string[] dlls = m_project.GetDependencies(true, false, engine.IsTargetBigEndian); Debug.Assert(pes.Length == dlls.Length); // now we will re-deploy all system assemblies for (int i = 0; i < pes.Length; ++i) { string assemblyPath = pes[i]; string dllPath = dlls[i]; //is this a system assembly? string fileName = Path.ChangeExtension(Path.GetFileName(assemblyPath), null).ToLower(); bool fDeployNewVersion = true; if (systemAssemblies.ContainsKey(fileName)) { // get the version of the assembly on the device Debugging_Resolve_Assembly.Version deviceVer = (WireProtocol.Commands.Debugging_Resolve_Assembly.Version)systemAssemblies[fileName]; // get the version of the assembly of the project // We need to load the bytes for the assembly because other Load methods can override the path // with gac or recently used paths. This is the only way we control the exact assembly that is loaded. byte[] asmData = null; using (FileStream sr = new FileStream(dllPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { asmData = new byte[sr.Length]; sr.Read(asmData, 0, (int)sr.Length); } System.Reflection.Assembly assm = Assembly.Load(asmData); Version deployVer = assm.GetName().Version; // compare versions strictly, and deploy whatever assembly does not match the version on the device if (VsProject.TargetFrameworkExactMatch(deviceVer, deployVer)) { fDeployNewVersion = false; } else { //////////////////////////////////////////////// // !!! SPECIAL CASE !!! // // // // MSCORLIB cannot be deployed more than once // //////////////////////////////////////////////// if (assm.GetName().Name.ToLower().Contains("mscorlib")) { string message = string.Format("Cannot deploy the base assembly '{9}', or any of his satellite assemblies, to device - {0} twice. Assembly '{9}' on the device has version {1}.{2}.{3}.{4}, while the program is trying to deploy version {5}.{6}.{7}.{8} ", this.DeployDeviceDescription, deviceVer.iMajorVersion, deviceVer.iMinorVersion, deviceVer.iBuildNumber, deviceVer.iRevisionNumber, deployVer.Major, deployVer.Minor, deployVer.Build, deployVer.Revision, assm.GetName().Name); VsPackage.MessageCentre.DeploymentMsg(message); SetDeployFailure(message); return; } } } // append the assembly whose version does not match, or that still is not on the device, to the blob to deploy if (fDeployNewVersion) { using (FileStream fs = File.Open(assemblyPath, FileMode.Open, FileAccess.Read)) { VsPackage.MessageCentre.DeploymentMsg(String.Format(DiagnosticStrings.AddingPEtoBundle, assemblyPath)); long length = (fs.Length + 3) / 4 * 4; byte[] buf = new byte[length]; fs.Read(buf, 0, (int)fs.Length); assemblies.Add(buf); } } } VsPackage.MessageCentre.DeploymentMsg("Attempting deployment..."); if (!engine.Deployment_Execute(assemblies, false, VsPackage.MessageCentre.DeploymentMsg)) { VsPackage.MessageCentre.DeploymentMsg(DiagnosticStrings.DeployFailed); SetDeployFailure(); return; } } finally { process.DetachFromEngine(); } }