吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3436|回复: 38
收起左侧

[Java 原创] 微信多开小工具JAVA版

  [复制链接]
feiMathRandom 发表于 2025-7-2 10:10
使用说明:
1、第一次使用需要拖拽微信快捷方式到软件里面,第二次使用就可以直接点多开了。
2、使用环境:windows 、 jdk1.8 、微信3.9或微信4.0

附图:

1751421879566.png

拖拽

拖拽

1751422133696.png

下面直接上源码:
[Java] 纯文本查看 复制代码
package com;

import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.text.ParseException;
import java.util.prefs.Preferences;

public class WeixinMore extends JFrame {

    private final JTextArea textArea = new JTextArea();
    private String currentFilePath = null;
    private static final String PREF_KEY = "wechat_shortcut_path";
    private final Preferences prefs = Preferences.userNodeForPackage(WeixinMore.class);

    public WeixinMore() {
        super("微信多开小助手");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(500, 300);
        setLocationRelativeTo(null);

        // 加载上次保存的路径
        loadSavedPath();

        JPanel dropPanel = createDropPanel();
        JPanel bottomPanel = createBottomPanel();

        setLayout(new BorderLayout(10, 10));
        add(dropPanel, BorderLayout.CENTER);
        add(bottomPanel, BorderLayout.SOUTH);

        setVisible(true);
    }

    private void loadSavedPath() {
        String savedPath = prefs.get(PREF_KEY, null);
        if (savedPath != null && !savedPath.isEmpty()) {
            File file = new File(savedPath);
            if (file.exists() && (file.getName().toLowerCase().endsWith("wechat.exe")
                    || file.getName().toLowerCase().endsWith("weixin.exe"))) {
                currentFilePath = savedPath;
                updateTextArea();
            } else {
                // 如果保存的路径无效,清除它
                prefs.remove(PREF_KEY);
            }
        }
    }

    private void savePath(String path) {
        if (path != null && !path.isEmpty()) {
            prefs.put(PREF_KEY, path);
            try {
                prefs.flush();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private JPanel createDropPanel() {
        JPanel panel = new JPanel(new GridBagLayout()) {
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                // 绘制虚线边框
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.setColor(Color.GRAY);
                g2d.setStroke(new BasicStroke(2, BasicStroke.CAP_ROUND,
                        BasicStroke.JOIN_ROUND, 1, new float[]{5}, 0));
                g2d.drawRect(5, 5, getWidth() - 11, getHeight() - 11);
                g2d.dispose();
            }
        };

        panel.setBackground(new Color(240, 245, 250));
        panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

        JLabel label = new JLabel("<html><div style='text-align:center;'>"
                + "拖拽微信快捷方式到此处<br><font size='2' color='#888'>(仅支持快捷方式文件)</font></div></html>");
        label.setFont(new Font("微软雅黑", Font.BOLD, 18));
        panel.add(label);

        // 设置拖拽目标
        new DropTarget(panel, new DropTargetAdapter() {
            @Override
            public void drop(DropTargetDropEvent dtde) {
                try {
                    dtde.acceptDrop(DnDConstants.ACTION_COPY);

                    // 获取拖拽的文件列表
                    java.util.List<File> files = (java.util.List<File>)
                            dtde.getTransferable().getTransferData(DataFlavor.javaFileListFlavor);

                    // 验证文件
                    if (files.size() == 0) {
                        JOptionPane.showMessageDialog(panel, "未接收到文件", "错误", JOptionPane.ERROR_MESSAGE);
                    } else if (files.size() > 1) {
                        JOptionPane.showMessageDialog(panel, "仅支持拖拽单个文件", "错误", JOptionPane.WARNING_MESSAGE);
                    } else {
                        File file = files.get(0);
                        String fileName = file.getName().toLowerCase();

                        // 验证文件扩展名
                        if (!fileName.endsWith(".lnk")) {
                            JOptionPane.showMessageDialog(panel,
                                    "只支持快捷方式文件 (.lnk)\n" +
                                            "您拖拽的是: " + fileName,
                                    "文件类型错误",
                                    JOptionPane.ERROR_MESSAGE);
                            dtde.rejectDrop();
                            return;
                        }

                        // 更新文件路径并保存
                        currentFilePath = file.getAbsolutePath();
                        currentFilePath = WindowsShortcut.getLinkTargetPath(currentFilePath);
                        savePath(currentFilePath);
                        updateTextArea();

                        // 添加视觉反馈
                        panel.setBackground(new Color(230, 245, 255)); // 反馈色
                        new Timer(500, e -> panel.setBackground(new Color(240, 245, 250))).start();
                    }

                    dtde.dropComplete(true);
                } catch (Exception ex) {
                    dtde.dropComplete(false);
                    JOptionPane.showMessageDialog(panel, "错误: " + ex.getMessage(), "读取失败",
                            JOptionPane.ERROR_MESSAGE);
                }
            }
        });

        return panel;
    }

    private JPanel createBottomPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));

        // 左侧文本区域
        JScrollPane scrollPane = new JScrollPane(textArea);
        textArea.setEditable(false);
        textArea.setFont(new Font("微软雅黑", Font.PLAIN, 14));
        textArea.setLineWrap(true);
        panel.add(scrollPane, BorderLayout.CENTER);

        // 右侧按钮区域
        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 0));

        // 清除路径按钮
        JButton clearButton = new JButton("清除路径");
        clearButton.setFont(new Font("微软雅黑", Font.PLAIN, 12));
        clearButton.setPreferredSize(new Dimension(90, 30));
        clearButton.addActionListener(e -> {
            currentFilePath = null;
            prefs.remove(PREF_KEY);
            updateTextArea();
            JOptionPane.showMessageDialog(this, "已清除保存的路径", "提示", JOptionPane.INFORMATION_MESSAGE);
        });
        buttonPanel.add(clearButton);

        // 微信双开按钮
        JButton wechatButton = new JButton("启动微信双开");
        wechatButton.setFont(new Font("微软雅黑", Font.BOLD, 14));
        wechatButton.setPreferredSize(new Dimension(130, 35));
        wechatButton.setBackground(new Color(7, 193, 96)); // 微信绿
        wechatButton.setForeground(Color.WHITE);
        wechatButton.setFocusPainted(false);
        buttonPanel.add(wechatButton);

        panel.add(buttonPanel, BorderLayout.EAST);

        // 添加按钮点击事件
        wechatButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                startDoubleWeChat();
            }
        });

        return panel;
    }

    private void updateTextArea() {
        if (currentFilePath != null) {
            textArea.setText("当前微信路径:\n" + currentFilePath);
        } else {
            textArea.setText("");
        }
    }

    private void startDoubleWeChat() {
        try {
            // 如果当前没有路径,尝试加载保存的路径
            if (currentFilePath == null) {
                String savedPath = prefs.get(PREF_KEY, null);
                if (savedPath != null && !savedPath.isEmpty()) {
                    currentFilePath = WindowsShortcut.getLinkTargetPath(savedPath);
                    updateTextArea();
                }
            }

            // 尝试通过文件路径启动微信
            if (currentFilePath != null && (currentFilePath.toLowerCase().endsWith("wechat.exe")
                    || currentFilePath.toLowerCase().endsWith("weixin.exe"))) {
                // 直接使用cmd命令启动快捷方式两次
                Runtime.getRuntime().exec(currentFilePath);
                Thread.sleep(1000); // 等待1秒
                Runtime.getRuntime().exec(currentFilePath);

                // 成功提示
                JOptionPane.showMessageDialog(this,
                        "微信双开已启动成功!",
                        "操作成功",
                        JOptionPane.INFORMATION_MESSAGE);
                return;
            } else {
                // 错误处理
                int choice = JOptionPane.showConfirmDialog(this,
                        (currentFilePath == null ? "未设置微信路径" : "路径无效: " + currentFilePath) +
                                "\n\n是否尝试手动定位微信程序或快捷方式?",
                        "微信启动失败",
                        JOptionPane.YES_NO_OPTION,
                        JOptionPane.ERROR_MESSAGE);

                // 如果用户选择手动定位
                if (choice == JOptionPane.YES_OPTION) {
                    JFileChooser chooser = new JFileChooser();
                    chooser.setDialogTitle("选择微信程序或快捷方式");

                    // 默认打开微信可能的安装位置
                    chooser.setCurrentDirectory(new File("C:\\Program Files (x86)\\Tencent\\WeChat"));
                    chooser.setFileFilter(new javax.swing.filechooser.FileFilter() {
                        @Override
                        public boolean accept(File f) {
                            return f.isDirectory() ||
                                    f.getName().equalsIgnoreCase("WeChat.exe") ||
                                    f.getName().equalsIgnoreCase("Weixin.exe");
                        }

                        @Override
                        public String getDescription() {
                            return "微信程序或快捷方式 (*.exe, *.lnk)";
                        }
                    });

                    if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
                        File selectedFile = chooser.getSelectedFile();
                        String selectedPath = selectedFile.getAbsolutePath();

                        // 如果是快捷方式,获取真实路径
                        if (selectedPath.toLowerCase().endsWith(".lnk")) {
                            currentFilePath = WindowsShortcut.getLinkTargetPath(selectedPath);
                            savePath(currentFilePath);
                        } else {
                            currentFilePath = selectedPath;
                        }

                        textArea.setText("已选择: " + currentFilePath);

                        // 尝试再次启动
                        try {
                            Runtime.getRuntime().exec(currentFilePath);
                            Thread.sleep(1000); // 等待1秒
                            Runtime.getRuntime().exec(currentFilePath);

                            JOptionPane.showMessageDialog(this,
                                    "微信双开已成功启动!",
                                    "操作成功",
                                    JOptionPane.INFORMATION_MESSAGE);
                        } catch (Exception ex2) {
                            JOptionPane.showMessageDialog(this,
                                    "启动失败: " + ex2.getMessage(),
                                    "错误",
                                    JOptionPane.ERROR_MESSAGE);
                        }
                    }
                }
            }
        } catch (Exception e) {
            JOptionPane.showMessageDialog(this,
                    "启动失败: " + e.getMessage(),
                    "错误",
                    JOptionPane.ERROR_MESSAGE);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            WeixinMore frame = new WeixinMore();
            frame.setVisible(true);
        });
    }

    public static class WindowsShortcut {
        private boolean isDirectory;
        private boolean isLocal;
        private String real_file;

        public static boolean isPotentialValidLink(File file) throws IOException {
            final int minimum_length = 0x64;
            InputStream fis = new FileInputStream(file);
            boolean isPotentiallyValid;
            try {
                isPotentiallyValid = file.isFile()
                        && file.getName().toLowerCase().endsWith(".lnk")
                        && fis.available() >= minimum_length
                        && isMagicPresent(getBytes(fis, 32));
            } finally {
                fis.close();
            }
            return isPotentiallyValid;
        }

        public WindowsShortcut(File file) throws IOException, ParseException {
            try (InputStream in = new FileInputStream(file)) {
                parseLink(getBytes(in));
            }
        }

        public String getRealFilename() { return real_file; }
        public boolean isLocal() { return isLocal; }
        public boolean isDirectory() { return isDirectory; }

        private static byte[] getBytes(InputStream in) throws IOException { return getBytes(in, null); }

        private static byte[] getBytes(InputStream in, Integer max) throws IOException {
            ByteArrayOutputStream bout = new ByteArrayOutputStream();
            byte[] buff = new byte[256];
            while (max == null || max > 0) {
                int n = in.read(buff);
                if (n == -1) break;
                bout.write(buff, 0, n);
                if (max != null) max -= n;
            }
            in.close();
            return bout.toByteArray();
        }

        private static boolean isMagicPresent(byte[] link) {
            final int magic = 0x0000004C;
            return link.length >= 32 && bytesToDword(link) == magic;
        }

        private void parseLink(byte[] link) throws ParseException {
            try {
                if (!isMagicPresent(link)) throw new ParseException("Invalid shortcut : magic is missing", 0);
                byte flags = link[0x14];
                byte file_attrs = link[0x18];
                isDirectory = (file_attrs & 0x10) > 0;
                final byte has_shell_mask = (byte) 0x01;
                int shell_len = 0;
                if ((flags & has_shell_mask) > 0) shell_len = bytesToWord(link, 0x4c) + 2;
                int file_start = 0x4c + shell_len;
                int file_location_info_flag = link[file_start + 0x08];
                isLocal = (file_location_info_flag & 2) == 0;
                int finalName_offset = link[file_start + 0x18] + file_start;
                String finalName = getNullDelimitedString(link, finalName_offset);
                if (isLocal) {
                    int baseName_offset = link[file_start + 0x10] + file_start;
                    String baseName = getNullDelimitedString(link, baseName_offset);
                    real_file = baseName + finalName;
                } else {
                    int networkVolumeTable_offset = link[file_start + 0x14] + file_start;
                    int shareName_offset = link[networkVolumeTable_offset + 0x08] + networkVolumeTable_offset;
                    String shareName = getNullDelimitedString(link, shareName_offset);
                    real_file = shareName + "\\" + finalName;
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                throw new ParseException("Could not be parsed, probably not a valid WindowsShortcut", 0);
            }
        }

        private static String getNullDelimitedString(byte[] bytes, int off) {
            int len = 0;
            while (bytes[off + len] != 0) len++;
            return new String(bytes, off, len);
        }

        private static int bytesToWord(byte[] bytes, int off) {
            return ((bytes[off + 1] & 0xff) << 8) | (bytes[off] & 0xff);
        }

        private static int bytesToDword(byte[] bytes) {
            return (bytesToWord(bytes, 2) << 16) | bytesToWord(bytes, 0);
        }

        public static String getLinkTargetPath(String linkPath) {
            File file = new File(linkPath);
            WindowsShortcut windowsShortcut;
            try {
                windowsShortcut = new WindowsShortcut(file);
            } catch (IOException | ParseException e) {
                return "";
            }
            return windowsShortcut.getRealFilename();
        }
    }
}

免费评分

参与人数 3吾爱币 +2 热心值 +3 收起 理由
blankTest001 + 1 我很赞同!
nbcty + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
lzd759125184 + 1 + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

duan0285 发表于 2025-7-3 11:50
@echo off
start "" "D:\WeChat\WeChat.exe"
start "" "D:\WeChat\WeChat.exe"
exit

放在文本文档,保存后,扩展名改为bat也可以。
kboylang 发表于 2025-7-10 13:08
怎么使用啊?我下载下来也把快捷方式拖进文件框里面了,提示启动成功。当时再点击微信图标,还是只有一个微信啊。也没有第二个微信登陆的页面出来啊?
 楼主| feiMathRandom 发表于 2025-7-2 10:41
可直接运行版本:
蓝州云下载地址:https://wwqv.lanzout.com/igCsQ303a2gf
密码:14hr
破解粉丝 发表于 2025-7-2 10:52
谢谢分享,有试过的吗?
melo520 发表于 2025-7-2 10:55
jdk1.8打包exe是怎么实现的
Finssss 发表于 2025-7-2 11:02
一直用的是论坛分享的另一款,学习学习
kk3201 发表于 2025-7-2 11:38
可惜没有mac的
楚吾爱 发表于 2025-7-2 12:09
回车 + 鼠标右键, 疯狂打击
 楼主| feiMathRandom 发表于 2025-7-2 12:11
melo520 发表于 2025-7-2 10:55
jdk1.8打包exe是怎么实现的

用的是软件:exe4j
jun269 发表于 2025-7-2 12:15
melo520 发表于 2025-7-2 10:55
jdk1.8打包exe是怎么实现的

专门有这样的打包exe的工具的
lzd759125184 发表于 2025-7-2 13:43
下载试试  不会封吧 ?
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-6-14 15:28

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表