public bool UpdateResources(string filename, BuildResults results)
        {
            bool      returnValue              = true;
            int       beginUpdateRetries       = 20;  // Number of retries
            const int beginUpdateRetryInterval = 100; // In milliseconds
            bool      endUpdate = false;              // Only call EndUpdateResource() if this is true

            // Directory.GetCurrentDirectory() has previously been set to the project location
            string filePath = System.IO.Path.Combine(Directory.GetCurrentDirectory(), filename);

            if (_stringResources.Count == 0 && _fileResources.Count == 0)
            {
                return(true);
            }
            IntPtr hUpdate = IntPtr.Zero;

            try
            {
                hUpdate = NativeMethods.BeginUpdateResourceW(filePath, false);
                while (IntPtr.Zero == hUpdate && Marshal.GetHRForLastWin32Error() == ResourceUpdater.ERROR_SHARING_VIOLATION && beginUpdateRetries > 0) // If it equals 0x80070020 (ERROR_SHARING_VIOLATION), sleep & retry
                {
                    // This warning can be useful for debugging, but shouldn't be displayed to an actual user
                    // results.AddMessage(BuildMessage.CreateMessage(BuildMessageSeverity.Warning, "GenerateBootstrapper.General", String.Format("Unable to begin updating resource for {0} with error {1:X}, trying again after short sleep", filename, Marshal.GetHRForLastWin32Error())));
                    hUpdate = NativeMethods.BeginUpdateResourceW(filePath, false);
                    beginUpdateRetries--;
                    Thread.Sleep(beginUpdateRetryInterval);
                }
                // If after all that we still failed, throw a build error
                if (IntPtr.Zero == hUpdate)
                {
                    results.AddMessage(BuildMessage.CreateMessage(BuildMessageSeverity.Error, "GenerateBootstrapper.General", String.Format("Unable to begin updating resource for {0} with error {1:X}", filename, Marshal.GetHRForLastWin32Error())));
                    return(false);
                }

                endUpdate = true;

                if (hUpdate != IntPtr.Zero)
                {
                    foreach (StringResource resource in _stringResources)
                    {
                        byte[] data = StringToByteArray(resource.Data);

                        if (!NativeMethods.UpdateResourceW(hUpdate, (IntPtr)resource.Type, resource.Name, 0, data, data.Length))
                        {
                            results.AddMessage(BuildMessage.CreateMessage(BuildMessageSeverity.Error, "GenerateBootstrapper.General", String.Format("Unable to update resource for {0} with error {1:X}", filename, Marshal.GetHRForLastWin32Error())));
                            return(false);
                        }
                    }

                    if (_fileResources.Count > 0)
                    {
                        int    index      = 0;
                        byte[] countArray = StringToByteArray(_fileResources.Count.ToString("G", CultureInfo.InvariantCulture));
                        if (!NativeMethods.UpdateResourceW(hUpdate, (IntPtr)42, "COUNT", 0, countArray, countArray.Length))
                        {
                            results.AddMessage(BuildMessage.CreateMessage(BuildMessageSeverity.Error, "GenerateBootstrapper.General", String.Format("Unable to update count resource for {0} with error {1:X}", filename, Marshal.GetHRForLastWin32Error())));
                            return(false);
                        }

                        foreach (FileResource resource in _fileResources)
                        {
                            // Read in the file data
                            int    fileLength  = 0;
                            byte[] fileContent = null;
                            using (FileStream fs = System.IO.File.OpenRead(resource.Filename))
                            {
                                fileLength  = (int)fs.Length;
                                fileContent = new byte[fileLength];

                                fs.Read(fileContent, 0, fileLength);
                            }

                            // Update the resources to include this file's data
                            string dataName = string.Format(CultureInfo.InvariantCulture, "FILEDATA{0}", index);

                            if (!NativeMethods.UpdateResourceW(hUpdate, (IntPtr)42, dataName, 0, fileContent, fileLength))
                            {
                                results.AddMessage(BuildMessage.CreateMessage(BuildMessageSeverity.Error, "GenerateBootstrapper.General", String.Format("Unable to update data resource for {0} with error {1:X}", filename, Marshal.GetHRForLastWin32Error())));
                                return(false);
                            }

                            // Add this file's key to the resources
                            string keyName = string.Format(CultureInfo.InvariantCulture, "FILEKEY{0}", index);
                            byte[] data    = StringToByteArray(resource.Key);
                            if (!NativeMethods.UpdateResourceW(hUpdate, (IntPtr)42, keyName, 0, data, data.Length))
                            {
                                results.AddMessage(BuildMessage.CreateMessage(BuildMessageSeverity.Error, "GenerateBootstrapper.General", String.Format("Unable to update key resource for {0} with error {1:X}", filename, Marshal.GetHRForLastWin32Error())));
                                return(false);
                            }

                            index++;
                        }
                    }
                }
            }
            finally
            {
                if (endUpdate && !NativeMethods.EndUpdateResource(hUpdate, false))
                {
                    results.AddMessage(BuildMessage.CreateMessage(BuildMessageSeverity.Error, "GenerateBootstrapper.General", String.Format("Unable to finish updating resource for {0} with error {1:X}", filename, Marshal.GetHRForLastWin32Error())));
                    returnValue = false;
                }
            }

            return(returnValue);
        }
Exemple #2
0
 internal void AddMessage(BuildMessage message)
 {
     this.messages.Add(message);
 }
 internal void AddMessage(BuildMessage message)
 {
     this.messages.Add(message);
 }
        public bool UpdateResources(string filename, BuildResults results)
        {
            bool flag  = true;
            int  num   = 20;
            bool flag2 = false;

            if ((this.stringResources.Count == 0) && (this.fileResources.Count == 0))
            {
                return(true);
            }
            IntPtr zero = IntPtr.Zero;

            try
            {
                zero = Microsoft.Build.Tasks.Deployment.Bootstrapper.NativeMethods.BeginUpdateResourceW(filename, false);
                while (((IntPtr.Zero == zero) && (Marshal.GetHRForLastWin32Error() == -2147024864)) && (num > 0))
                {
                    zero = Microsoft.Build.Tasks.Deployment.Bootstrapper.NativeMethods.BeginUpdateResourceW(filename, false);
                    num--;
                    Thread.Sleep(100);
                }
                if (IntPtr.Zero == zero)
                {
                    results.AddMessage(BuildMessage.CreateMessage(BuildMessageSeverity.Error, "GenerateBootstrapper.General", new object[] { string.Format("Unable to begin updating resource for {0} with error {1:X}", filename, Marshal.GetHRForLastWin32Error()) }));
                    return(false);
                }
                flag2 = true;
                if (!(zero != IntPtr.Zero))
                {
                    return(flag);
                }
                foreach (StringResource resource in this.stringResources)
                {
                    byte[] buffer = this.StringToByteArray(resource.Data);
                    if (!Microsoft.Build.Tasks.Deployment.Bootstrapper.NativeMethods.UpdateResourceW(zero, (IntPtr)resource.Type, resource.Name, 0, buffer, buffer.Length))
                    {
                        results.AddMessage(BuildMessage.CreateMessage(BuildMessageSeverity.Error, "GenerateBootstrapper.General", new object[] { string.Format("Unable to update resource for {0} with error {1:X}", filename, Marshal.GetHRForLastWin32Error()) }));
                        return(false);
                    }
                }
                if (this.fileResources.Count <= 0)
                {
                    return(flag);
                }
                int    num2 = 0;
                byte[] data = this.StringToByteArray(this.fileResources.Count.ToString("G", CultureInfo.InvariantCulture));
                if (!Microsoft.Build.Tasks.Deployment.Bootstrapper.NativeMethods.UpdateResourceW(zero, (IntPtr)0x2a, "COUNT", 0, data, data.Length))
                {
                    results.AddMessage(BuildMessage.CreateMessage(BuildMessageSeverity.Error, "GenerateBootstrapper.General", new object[] { string.Format("Unable to update count resource for {0} with error {1:X}", filename, Marshal.GetHRForLastWin32Error()) }));
                    return(false);
                }
                foreach (FileResource resource2 in this.fileResources)
                {
                    int    count   = 0;
                    byte[] buffer3 = null;
                    using (FileStream stream = File.OpenRead(resource2.Filename))
                    {
                        count   = (int)stream.Length;
                        buffer3 = new byte[count];
                        stream.Read(buffer3, 0, count);
                    }
                    string lpName = string.Format(CultureInfo.InvariantCulture, "FILEDATA{0}", new object[] { num2 });
                    if (!Microsoft.Build.Tasks.Deployment.Bootstrapper.NativeMethods.UpdateResourceW(zero, (IntPtr)0x2a, lpName, 0, buffer3, count))
                    {
                        results.AddMessage(BuildMessage.CreateMessage(BuildMessageSeverity.Error, "GenerateBootstrapper.General", new object[] { string.Format("Unable to update data resource for {0} with error {1:X}", filename, Marshal.GetHRForLastWin32Error()) }));
                        return(false);
                    }
                    string str2    = string.Format(CultureInfo.InvariantCulture, "FILEKEY{0}", new object[] { num2 });
                    byte[] buffer4 = this.StringToByteArray(resource2.Key);
                    if (!Microsoft.Build.Tasks.Deployment.Bootstrapper.NativeMethods.UpdateResourceW(zero, (IntPtr)0x2a, str2, 0, buffer4, buffer4.Length))
                    {
                        results.AddMessage(BuildMessage.CreateMessage(BuildMessageSeverity.Error, "GenerateBootstrapper.General", new object[] { string.Format("Unable to update key resource for {0} with error {1:X}", filename, Marshal.GetHRForLastWin32Error()) }));
                        return(false);
                    }
                    num2++;
                }
            }
            finally
            {
                if (flag2 && !Microsoft.Build.Tasks.Deployment.Bootstrapper.NativeMethods.EndUpdateResource(zero, false))
                {
                    results.AddMessage(BuildMessage.CreateMessage(BuildMessageSeverity.Error, "GenerateBootstrapper.General", new object[] { string.Format("Unable to finish updating resource for {0} with error {1:X}", filename, Marshal.GetHRForLastWin32Error()) }));
                    flag = false;
                }
            }
            return(flag);
        }