EmEditor was reviewed in Mado-no-mori

A Revolutionary Text Editor Assisted by Generative AI is Here! Achieved with EmEditor Macros
– An In-depth Explanation of Macro Processing! Achieve a Kansai Dialect Conversion Feature with Extreme Modification!

EmEditor v24.0.1 released

Today, we are releasing EmEditor v24.0.1.

v24.0.1 includes the following bug fixes.

  • Fixed an issue that caused the import and export settings to inadvertently copy a device ID to another computer.
  • Fixed a bug where selecting a single column without “Cell Selection Mode” enabled would not copy the right-side delimiter.
  • Fixed a bug where selecting and converting (for example, to Uppercase) a column in a CSV with invalid syntax would convert the entire line.
  • Fixed customer-reported issues (1, 2).

If you use the Desktop Installer version, you can select Check for Updates on the Help to download the newest version. If this method fails, please download the newest version, and run the downloaded installer. If you use the Desktop portable version, you can go to the Download page to download the newest version. The Store App versions can be updated through Microsoft Store (64-bit or 32-bit) after a few days.

EmEditor v24.0.0 released (including technical review)

Today, we are releasing EmEditor v24.0.0.

In the previous version, v23.1, we introduced how to use generative AI by calling OpenAI‘s API from macros. Typically, text is used as an argument for invoking generative AI, which suggests a high affinity between text editors and generative AI. When writing documents in a text editor, one of the purposes of using generative AI is to proofread the document. In this use case, you would want to easily compare the document before and after proofreading to easily decide which parts of the changed text to keep or discard. In this version, we added a “Copy to Other” command to the context menu that appears when right-clicking on the changed text while comparing documents in a split window. Selecting this will copy the changed part to the other document being compared. If you want to copy all changes in the document at once, click the “Copy All to Other” button newly added at the title part of the split window.

After the comparison is done, you may want to close unnecessary documents and keep only the needed ones. In such cases, you can now close only the document in the currently active pane by clicking the newly added [X (Close)] button or pressing Ctrl+W or Ctrl+F4.

We further developed the library’s ChatOpenAI.jsee macro example and added it to EmEditor by default under the name AI.jsee. By using the AI macro, you can perform proofreading, summarization, translation, generate images, or ask questions to AI for selected text or the entire document. When you run this macro for the first time, you will be prompted to enter your OpenAI API key. If you are logged into OpenAI, you can get your secrect OpenAI API key by visiting here. To skip entering this key in the future, please set the environment variable OPENAI_API_KEY.

In this version, we have also responded to many requests from our customers.

1. Onigmo regular expressions now support the \Q...\E syntax. This syntax allows you to disable regular expression metacharacters without needing to escape them. For example, to search for the string [a.c], the conventional regular expression would require you to escape the metacharacters "[", ".", "]" with backslashes, \[a\.c\]. In the new version, you can simply write \Q[a.c]\E, eliminating the need to escape metacharacters. Note that Boost‘s Regex has supported the \Q...\E syntax for some time.

2. We added an option to the Find Next and Find Previous commands that only matches non-overlapping strings. For example, if you search for “AA” in the string “AAAAA”, initially only the first four characters, “AAAA”, are highlighted. When you execute the Find Next (F3) command, the search position shifts one character at a time, allowing you to search through all the “AA” pairs. With this version, setting the Find only non-overlapping strings in Find Next/Previous checkbox in the Advanced dialog box makes the command operate in a way that only non-overlapping strings match, ending the search leaving the last “A” unsearched, thus aligning the highlight with the search position.

3. In EmEditor, URI and email addresses are highlighted, and we frequently receive requests to extract just those parts. In previous versions, this could be done by specifying an appropriate regular expression in the Find dialog and selecting Extract, but many of our customers are not familiar with regular expressions. In this version, you can easily extract just the URIs or email addresses by specifying options in the Extract Frequent Strings command.

4. When opening a CSV in EmEditor, the delimiter positions are automatically adjusted by default. However, very long cells can cause the column width to become very wide, making the entire CSV hard to view. In this version, we added a Maximum column width textbox to the CSV Options page of the Customize dialog, allowing you to specify the maximum column width.

5. In the previous version, EmEditor started displaying a warning message when a file opened in it was deleted by another application. In this version, you can choose whether or not to display the warning message. It can be specified on the File page of the Configuration Properties via the Prompt if file deleted checkbox.

6. Some customers have reported slow startup times for EmEditor on recent versions of Windows 11. This is primarily due to the retrieval of the Windows Clipboard History during startup. The new version has this option disabled by default, but it can be enabled on the Clipboard page of the Customize dialog.

7. The new version disables the Switch to no wrap option in the Compare Files wizard by default.

Furthermore, in this version, we have significantly optimized commands like Split a File, Combine Files, Increase Line Indent, Decrease Line Indent, achieving a speed increase of 27 to 124 times compared to v23.1, according to our tests.

As announced by Makoto Emura on his blog, starting from this version, a warning message may appear if you use EmEditor Professional on more devices than allowed by the EULA (end-user license agreement). To maintain our lower license fees and ensure fairness among customers who have purchased multiple licenses, please purchase enough licenses to follow the terms of the license.

Uninstalling EmEditor unregisters the device, allowing you to install it on a different device. You can view your registered devices here. We have unregistered all devices when v24.0.0 was released so that old devices will be unregistered. When you use EmEditor, the device will automatically be registered.

I hope you like EmEditor, whether you use the Professional or Free version. Please contact us or write in forums if you have any questions, feature requests, or any ideas in the future.

Thank you for using EmEditor!
Yutaka Emura

Please see EmEditor v24.0 New Features for details and screenshots.

If you use the Desktop Installer version, you can select Check for Updates on the Help menu to download the newest version. If this method fails, please download the newest version, and run the downloaded installer. If you use the Desktop portable version, you can go to the Download page to download the newest version. The Store App versions can be updated through Microsoft Store (64-bit or 32-bit) after a few days.

EmEditor v23.1.3 released

Today, we are releasing EmEditor v23.1.3.

v23.1.3 includes the following bug fixes.

  • Fixed a potential issue of v23.1.2 where a portion of a very large file might not be saved.

Please see EmEditor v23.1 New Features for details and screenshots.

If you use the Desktop Installer version, you can select Check for Updates on the Help to download the newest version. If this method fails, please download the newest version, and run the downloaded installer. If you use the Desktop portable version, you can go to the Download page to download the newest version. The Store App versions can be updated through Microsoft Store (64-bit or 32-bit) after a few days.

New Validation System Explained

On version 24.0.0, we introduced a registration validation system to improve the already existing registration system. This validation system is able to track the number of devices a customer has registered EmEditor on.

This blog serves to be transparent about our motivations and to document how the validation system works. If we update the validation system in the future, we will also update this page.

Stripe update

On May 2024, this document was updated to include the Stripe payment flow. The ability to pay on Stripe is a planned feature.

Motivation

In the past, there was no way for us to detect a user who is sharing their license with ten other people, or those who are using their license on more devices than allowed by the EULA (end-user license agreement). We would like customers to purchase enough licenses to follow the terms of the license. This would ensure fairness among customers who have purchased multiple licenses.

Requirements

This section lists the requirements we had for the validation system.

Functional

  • The validation system should loosely enforce the device limit clause of the license. It should not sacrifice customer satisfaction, so we should not make this limit a surprise.
  • Registration is run once upon submission of the Register Product dialog box or any of the other registration flows. Validation is run once every time the EmEditor is opened.
  • Registration requires EmEditor to be able to connect to support.emeditor.com via HTTP. Validation does not require internet connection.
  • Users should be able to use an offline license that allows the app to register and validate without connecting to our server. In case a user experiences errors with normal registration, an offline license would allow an alternative way to register.
  • Privacy rights of users should be maintained. The collection of personal information will be opt-in.
  • It should fit into the existing registration system and not make it a new way to register. Current users should be able to register without having to learn new steps.
    • Uninstalling the app should unregister the device.
  • Users can log in to the Emurasoft Customer Center to view devices so that devices can be unregistered outside of the app.
  • Customers who have purchased from non-2Checkout resellers will have to register the product and create a customer center account. This is because there will be no way for them to see their devices online without an account.
  • The system should be tested in the background in version 23. It should be fully in effect from version 24.

Technical

  • The system should be simple so that it is easier to maintain.
  • A machine can be identified with a machine ID.
    • We determined that the registry value
      HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\MachineGuid
      is a suitable ID.
    • EmEditor Portable can be installed on a USB, with its settings stored in the USB. The USB can be used on many machines, and the validation system would detect different machine IDs. Therefore if the app detects that it is a portable version running on a USB, registration does not occur.
  • EmEditor can be installed per-user on a multi-user machine. We must combine all EmEditor installations on the same machine as one unit to the device count.
  • There should be a way to override the limit for a given registration key, just in case.
  • A signed token containing the device info should be stored on the user’s device. This associates the current device with the device record stored in the database.
  • The system should be able to integrate a floating license system if we decide to in the future.

Output

  • You can view a list of all devices on the Registered Devices page of customer center.
  • If the device limit is reached, a notification will appear. The user can still use the app even if the device limit is exceeded.

  • If the user bought the app from a non-2Checkout reseller and has not registered the product, a notification will ask the user to register the product.

Device table

The device table is stored in our database and records all devices that were registered. Note that a History record is associated with a purchase and it is where a registration key is stored. A Device record is defined in Go as follows.

type Device struct {
	DeviceID             string
	UserID               int
	HistoryID            sql.NullInt64
	StripeSubscriptionID sql.NullString
	MachineID            uuid.UUID
	RegistrationDate     time.Time
	ValidationDate       time.Time
	InstallationType     InstallationType
	Label                string
	Unregistered         bool
}

The fields are explained in the documentation for Registered Devices.

Privacy measures for label

The Label field may contain personal information. The Label device field in the Register Product dialog box defaults to {computer name} {user name}. The personal information inside the label field is not necessary for the basic functionality of the app. Therefore, we made the label field opt-in to stick to our policy of privacy by default.

Local Device token

A LocalDevice token is stored locally on the user’s device in the form of a JWT (JSON Web Token). It associates the current device with the database Device record. It also allows EmEditor to do some validation even if it is offline. The token payload is defined as follows.

type LocalDevice struct {
	DeviceID  string
	MachineID uuid.UUID

	// StripeSubscriptionID is empty if this device is not associated with a subscription.
	StripeSubscriptionID string
}

The expiration date of the token is set to the expiration date of the registration key.

For per-user installations, the token is stored in the registry as LocalDeviceToken in Computer\HKEY_CURRENT_USER\Software\EmSoft\EmEditor v3\Common.

Device count

This section describes how we determine how many devices you can register. This is subject to change if we change the terms of the EULA.

To calculate the number of units towards the device limit for a specific registration key, we use the following MySQL query.

SELECT count(DISTINCT MachineID) as deviceCount
FROM devices
WHERE HistoryID=? AND Unregistered=FALSE

For Stripe subscriptions, the following query is used.

SELECT count(DISTINCT MachineID) as deviceCount
FROM devices
WHERE StripeSubscriptionID=? AND Unregistered=FALSE

For a given history ID, we first get all devices that are still registered. Then we count the number of unique machines. If there are multiple devices with the same MachineID, they are likely multiple per-user installations on the same machine.

The EULA allows the licensee to install EmEditor to up to two devices per license. If EmEditor is for personal use and not installed on corporate computers, the licensee can install EmEditor to five devices per license.

Offline registration

An offline license allows a user to register without an internet connection. Registration only requires a license file.

A customer can request an offline license file. The customer must include their registration key or Stripe order ID in the request. We will reply to the customer’s email address within a few business days with the license file. The license file is a text file that contains a JWT token with the following payload.

type LicenseFile struct {
	LicenseID string
	UserID    int
	FullName  string
	Email     string

	// Is nil if not a Stripe subscription
	StripeSubscriptionID *string

	// Is nil if not a registration key
	HistoryID *int
}

The offline license token is saved to the registry entry OfflineLicense.

There are three ways that the device limit is enforced and illegal sharing of the license file is prevented. 1) When EmEditor can access the internet, validation is performed. 2) We will only send the license file via email instead of downloading from our website. 3) The Registration Information dialog will display the license owner’s full name and email.

OfflineLicense table

Usage of offline licenses is tracked using the OfflineLicense table. It includes the machine ID to track how many machines used the license and the Revoked flag to allow us to revoke a license.

type OfflineLicense struct {
	LicenseID            string
	UserID               int
	MachineID            uuid.UUID
	StripeSubscriptionID sql.NullString
	HistoryID            sql.NullInt64

	// Revoked indicates that this license cannot be used
	Revoked bool
}

Registration Information dialog box

Registration Information displays information about the user’s registration. This is useful for knowing what your registration status is, and to diagnose any issues with validation. It also allows the user to edit the device information and to unregister.

The dialog runs validation and shows whether or not it was successful.

Registration process

There are four scenarios where registration may happen.

  • Most users will register through the Register Product dialog box.
  • Register using the MSI installer.
  • Offline registration using the command line.
  • If you unregistered a device, then opened EmEditor on that device, the device will be registered automatically.

There are two online registration flows, depending on if a registration key is used (RegisterDevice()) or a Stripe subscription is used (RegisterDeviceSubscription()). The third registration flow is for offline registration (StoreOfflineLicenseAndValidate()).

In this section, “Client” refers to the local EmEditor app on the user’s machine. “Server” is our backend server and database.

If the user signed in, the server tries to find a valid Stripe subscription that has not exceeded the device limit. If there is a usable Stripe subscription, RegisterDeviceSubscription() is called. If such Stripe subscription does not exist, it will find a valid registration key that has not exceeded the device limit. RegisterDevice() is used for registration keys.

Registration with registration key (RegisterDevice())

  1. If a device token already exists, the client sends an unregister request to the server. The token and registration key is deleted from the registry.
  2. The client sends a registration request to the server, which includes the registration key, machine ID, label, and installation type.
  3. The server queries deviceCount (defined in previous section) to determine if the registration key can be used to register the device
  4. A Device record is created.
  5. The client receives the device ID. Using the device ID, the client requests a local device token.
  6. The server creates and responds with the local device token. The expiration date of the token is set to the registration key expiration date. The client writes the token to local storage.

Registration with Stripe subscription (RegisterDeviceSubscription())

  1. If a device token already exists, the client sends an unregister request to the server. The token and registration key is deleted from the registry.
  2. The client sends a registration request to the server, which includes the Stripe subscription, machine ID, label, and installation type.
  3. The server queries deviceCount (defined in previous section) to determine if the Stripe subscription can be used to register the device.
  4. A Device record is created.
  5. The client receives the device ID. Using the device ID, the client requests a local device token.
  6. The server creates and responds with the local device token. The expiration is set to one month in the future if the subscription status is active. If the subscription status is canceled, the expiration date is set to the end date of the current billing period. The client writes the token to local storage.

Registration with offline license (StoreOfflineLicenseAndValidate())

The user registers an offline license by saving the license file to the filesystem, then running the command line option

/ol "licenseFilePath"

This list outlines the offline registration process.

  1. Delete the registration key, local device token, and offline license token from the registry.
  2. Read the license file and save it to the registry.
  3. Run ValidateDevice().

Validation process (ValidateDevice())

Validation occurs every time the app is opened.

  1. If local device token does not exist in the registry, call ValidateOfflineLicense().
  2. The token’s signature is validated. The actual machine ID is compared with the machine ID in the token. The result is ignored if the app is running on a removable drive.
    • If validation fails due to expected reasons such as a mismatched machine ID, the reason is outputted as status text, and the device token is deleted.
    • For other unexpected errors such as network error, validation succeeds.
  3. A random number generator determines if validation should stop here. This is to reduce the load of requests to our server.
  4. The validation function sleeps the thread for a certain duration. This is again to reduce the request load, as we assume that macros and other automated use cases that rapidly start and close the app would only run it for a short duration.
  5. The client requests the Device data for the stored device ID.
  6. If device.Unregistered == true, the client attempts to register the device.
  7. The device.ValidationDate is updated.
  8. If the token was issued before current time – 7 days, a new token is created to replace the old token.

Offline license validation process (ValidateOfflineLicense())

Offline license validation occurs if the registry does not contain the local device token. If an unexpected error occurs, validation succeeds. This means that if the user is offline, validation will still succeed.

  1. If the offline license token does not exist, validation succeeds. One case where this may happen is if registration previously failed due to a network error but the registration key was valid. This allows EmEditor to be used in such case.
  2. Read and validate the token.
  3. Request the server to validate the offline license with the token and machine ID.
  4. The server validates the token.
  5. For Stripe subscriptions, the server checks that the subscription exists.
  6. If an OfflineLicense entry for the license ID does not exist, it is created with the token data.
  7. If the entry exists and license.Revoked == true, it returns StatusLicenseRevoked. Otherwise validation succeeds.

Uninstallation

When you uninstall the desktop version of EmEditor, your device will automatically be unregistered. This makes it easy to install to another machine without having to unregister the previous device manually. Because the portable and Store App versions do not have an uninstallation process, they will not unregister automatically when you remove those apps. Therefore if you have a portable or Store App and you are no longer using it on your device, you must manually unregister it from the Registered Devices page in Customer Center.

Devices will be unregistered when version 24 is released

On the day that version 24 is released, all devices will be unregistered. In version 23, uninstallation did not unregister devices, so there are many devices that should be unregistered. After we unregister all devices, the devices that are in use will automatically register again.

Support

If you have any questions or feedback about the validation system, feel free to send us a message.

EmEditor v23.1.2 released

Today, we are releasing EmEditor v23.1.2.

v23.1.2 includes the following bug fixes.

  • Fixed various issues and improved the stability.

Please see EmEditor v23.1 New Features for details and screenshots.

If you use the Desktop Installer version, you can select Check for Updates on the Help to download the newest version. If this method fails, please download the newest version, and run the downloaded installer. If you use the Desktop portable version, you can go to the Download page to download the newest version. The Store App versions can be updated through Microsoft Store (64-bit or 32-bit) after a few days.

EmEditor v23.1.1 released

Today, we are releasing EmEditor v23.1.1.

v23.1.1 includes the following bug fixes.

  • Fixed a potential crash if an opened file contains invalid characters.
  • Fixed an unexpected behavior when using the BatchReplace method with the eeFindReplaceSelOnly flag while no selection exists.

If you use the Desktop Installer version, you can select Check for Updates on the Help to download the newest version. If this method fails, please download the newest version, and run the downloaded installer. If you use the Desktop portable version, you can go to the Download page to download the newest version. The Store App versions can be updated through Microsoft Store (64-bit or 32-bit) after a few days.

EmEditor v23.1.0 released (including technical review)

Today, we are releasing EmEditor v23.1.0.

In the previous version (v23.0), we introduced how to access the web page of the generated AI using macros and the built-in Web Browser in EmEditor and obtain various information and services. However, customers who have a paid API key for the generated AI site can obtain faster, higher-quality services with more stable operation by directly calling the API. To do this, the fetch function in JavaScript is used, but since this function operates asynchronously, the return value of the function may not be obtained before the macro ends. Actually, even in v23.0, it was possible to use this method if the built-in Web Browser in EmEditor was displayed, but there was a problem that async functions could not be used if the Web Browser was not displayed. In this new version (v23.1), by using the KeepRunning property, it is now possible to wait for the completion of the async function without ending the macro (EmEditor Professional only). Before calling the async function, specify the KeepRunning property as follows.


shell.KeepRunning = true;

This keeps the macro running, allowing you to obtain the return value of the async function. To end the macro after obtaining the return value of the async function, you can specify it as follows:


shell.KeepRunning = false;

This is almost equivalent to Quit() when waiting for the completion of async functions, and the macro ends immediately.

Below is a sample macro using the fetch function to utilize the OpenAI API. To run this sample macro, you need to replace {your-API-key} with your API key. When you run the following macro, it sends the question “How are you?” to the OpenAI API and displays the answer in the output bar.


#language="v8"

const apiKey = "{your-API-key}";

/**
 * Sends prompt to OpenAI and returns the response.
 * Docs: https://platform.openai.com/docs/guides/text-generation/chat-completions-api?lang=curl
 * @param {string} endpoint URL for request
 * @param {string} apiKey API key
 * @param {string} messageContent The prompt
 * @returns {string} The text content of the response
 */
async function callOpenAI(endpoint, apiKey, messageContent) {
    const response = await fetch(
        endpoint,
        {
            method: "POST",
            headers: {
                "Authorization": `Bearer ${apiKey}`,
                "content-type": "application/json",
            },
            body: JSON.stringify({
                "model": "gpt-3.5-turbo",
                "messages": [
                    {
                        "role": "user",
                        "content": messageContent,
                    }
                ],
            }),
        }
    );
    if (!response.ok) {
        alert(await response.text());
        Quit();
    }

    const responseObj = await response.json();
    if (responseObj.choices.length == 0) {
        alert("choices length is 0");
        Quit();
    }

    // Get content of first choice
    return responseObj.choices.pop().message.content;
}

async function main() {
    const endpoint = "https://api.openai.com/v1/chat/completions";
    const sPrompt = "How are you?";
    shell.KeepRunning = true;
    const response = await callOpenAI(endpoint, apiKey, sPrompt);
    OutputBar.writeln( response );
    OutputBar.Visible = true;
    shell.KeepRunning = false;
}
main();

The CharOpenAI.jsee macro example further extends this sample by displaying a popup menu of commonly used questions (“Proofread”, “Summarize”, “Look up”, “Translate”…) for the currently selected text or entire document. When a question is selected, it sends the question to the OpenAI API and displays the answer in the output bar.

Actually, I am using the CharOpenAI.jsee macro to translate and proofread while writing this blog. By combining the generated AI with a text editor, I have been able to significantly improve my work efficiency.

Another major change in v23.1 is the speed improvement when handling large files. In v23.0, changes to lines were stored in memory instead of temporary files for faster operation. However, in systems with limited memory, this could result in slowness or errors due to insufficient system memory. In v23.1, the memory-related algorithms have been revised to operate more efficiently. Additionally, when virtual memory becomes insufficient, it now uses temporary files to store data. As a result, users no longer need to worry about the size of virtual memory, and the frequency of crashes due to memory shortage has been significantly reduced. The improvements in code related to memory, as well as the use of multi-threading and the SIMD instruction set, have resulted in a speed increase of 1.51 to 41.2 times faster than v23.0 for many commands when editing huge files, including CSV files.

The Help feature now defaults to using an external browser instead of EmEditor’s built-in Web Browser, similar to v22.5 and earlier versions. Furthermore, the Help page has been added to the Customize dialog box, allowing users to change settings related to Help.

Lastly, Makoto Emura added the Completion List feature using the Language Server Protocol (LSP). To utilize this feature, the Language Server Protocol must be enabled in the Language Server page of configuration properties, and the Show completion list option is also enabled (EmEditor Professional only). Currently, only JavaScript supports this feature.

I hope you like EmEditor, whether you use the Professional or Free version. Please contact us or write in forums if you have any questions, feature requests, or any ideas in the future.

Thank you for using EmEditor!
Yutaka Emura

Please see EmEditor v23.1 New Features for details and screenshots.

This release also includes all bug fixes while developing v23.1.

If you use the Desktop Installer version, you can select Check for Updates on the Help to download the newest version. If this method fails, please download the newest version, and run the downloaded installer. If you use the Desktop portable version, you can go to the Download page to download the newest version. The Store App versions can be updated through Microsoft Store (64-bit or 32-bit) after a few days.

EmEditor Logo

EmEditor v23.1 preview

We are releasing EmEditor v23.1 preview versions for public testing. EmEditor v23.1 significantly enhanced the speed of numerous commands when editing very large files, including CSV, while also reducing crashes caused by low memory. The preview versions also include recent bug fixes. Please try the preview versions and let us know if you encounter any issues or have any feedback

Please see EmEditor v23.1 preview (23.0.901-) for the revision history.

To update: If you use the installer version, please select Customize Update Checker on the Help menu, and set the Include preview versions in order to update automatically to future preview versions. Preview versions can also be downloaded at Previous versions.

EmEditor v23.0.5 released!

Today, we are releasing EmEditor v23.0.5.

v23.0.5 includes the following bug fixes.

  • Fixed a potential crash when a CSV file is opened while the Character Code at Cursor is enabled on the status bar
  • Fixed a potential crash when the scroll bar minimap is displayed while the CSV validation is running.
  • Fixed a potential crash on the Indent command during the vertical selection mode while multiple selections were disabled.
  • Fixed a potential crash on the CommitList plug-in with Unicode path.
  • Fixed various Help issues (1).

Please see EmEditor v23.0 New Features for details and screenshots.

If you use the Desktop Installer version, you can select Check for Updates on the Help to download the newest version. If this method fails, please download the newest version, and run the downloaded installer. If you use the Desktop portable version, you can go to the Download page to download the newest version. The Store App versions can be updated through Microsoft Store (64-bit or 32-bit) after a few days.